开发者

How to setup a solution which has projects for winforms and web?

In my solution I have a few projects:

  • A core project. This project contains all my classes and interfaces
  • A Winforms project
  • A Web project

A key feature of the application is to dynamically generate controls. I have a class with an enum, and based on an enum value a particular control must be returned. So I've created a factory in the core project like this:

public IControl Create(Enum enum)
{
    switch(enum)
    {
      case "enum.A":
        return new CheckBoxControl();
      case "enum.B":
        return new RadioControl();
    }
}

Ass you might have guessed, I have custom controls. They all inherit from an Interface (IControl). But in this case, CheckBoxControl and RadioControl are开发者_运维百科 WinFroms controls.

Now, these controls resides in the core project. I don't want this, because it is a core library and I want this library to be platform independent.

I want the winforms controls in a WinCore project and the WebControls in a WebCore project. The problem is, How can I return the right controls from the core project?

Both, the WebCore and WinCore project need a reference to the core project, because the core project contains my entities. This means, that I can't set a reference from the core the web- or wincore project.

How to solve this?


I would do that:

  • .Core should be an assembly containing business.

  • .Shared should be an assembly containing infraestructure, base classes and interfaces that are platform and technology-independent - so this will let you referene it in any project avoiding unwanted dependencies -.

  • .Web should be the assembly containing web-oriented functionality

  • .Web.Forms should be the assembly containing Web Forms and Web Controls only.

  • .Windows should be the assembly contaning Windows-oriented functionality.

  • .Windows.Forms should be the assembly contaning Windows Forms and Controls only.

Having such assembly structure, IControl interface should be in .Shared assembly and this should be referenced by .Core, allowing code to add IControl instances without needing technology-specific dependencies.

In addition, this solution is enough to let .Windows, .Windows.Forms, .Web and .Web.Forms reference .Core and/or .Shared.


UPDATE:

It's just a suggestion, but why are you using an enumeration in your factory? You could do that:

public TControl Create<TControl>() where TControl : IControl, new()
{
    IControl control = new TControl();

    // Control initialization work

    return control;
}

What do you think?

Nevermind that, it was just a suggestion because maybe, with some refactoring, you could use this kind of factory method, but I can understand this is far from your current implementation. Concentrate better in my answer :)


UPDATE 2:

How inversion of control can help you in your problem?

In fact, if you register inversion of control components, you're going to access them by type or by some unique identifier.

Let's say you've the IControl interface (the service) and WindowsTextBox and WebFormsTextBox both implementing IControl. In your configuration file you're goint to have two components, which have both same service type (the interface) and two different implementations and these will be marked with two different identifiers:

  • WindowsTextBox is IControl, with identifier WindowsTextBox.
  • WebFormsTextBox is IControl, with identifier WebFormsTextBox.

Now you've both controls registered in your inversion of control container, and you can use own-API component retrieval factory like this:

  • IoCFactory.GetComponents<IControl>(). You want all IControl implementations in current inversion of control's container - not recommended in your case! -.

  • IoCFactory.GetComponent<IControl>("WindowsTextBox"). You want the IControl implementation called "WindowsTextBox".

In the second case, which is our focus now, you get an object typed as IControl, meaning you can access to its common members (properties, methods, events...).

Where's the point of inversion of control in your problem? Note you're using a factory class that would be placed in a shared library so you can use it anywhere, and same for IControl interface.

Right, I guess you need concrete control instances. You can do two things:

  • Just play with IControl instances and wherever, in a technology-specific logic, cast it to its concrete type - for example, WindowsTextBox - and go on.

  • Create as many interfaces that concrete more IControl, so some logic can access to some properties and methods that are closer to the concrete control feature set. An example of that would be a ITextBox interface and get any inversion of control component by this more concrete interface in the same way as I explained above.

I believe I gave enough hints in order to get an idea of how my solution structure and assembly organization, plus inversion of control, can give you such technology independence that you're looking between and within your project's layers! ;)


Add a Controlmanager to core with a method RegisterControls. Webcore calls the Controlmanager.RegisterControls method. The main app only talks to core


You should use a different factory in the WinForms project and in the Web project. Create a IControlFactory interface that is implemented in both factories, and instantiate the appropriate type of factory in each project.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜