How to Use Dependency Injection on UserControls & Forms

喜你入骨 提交于 2019-12-24 15:53:30

问题


Running into a knowledge gap, been out of WinForms for so long, unsure if i am doing this correctly for Castle Windsor.

For the last 5 years i have developing ASP.Net applications (WebForms, MVC, etc). I now have a project where a web interface is not a viable solution, yet. So we are doing it with WinForms.

With Asp.Net, i would have just set up the Castle Windsor Container, CWC, static class and everything would have taken care of itself for Dependency Injections, etc.

I am having some issues when it comes to WinForms. I evidently cant implement the same rules for Dependency Injection that i did for the WebForms developments.

Current Implementation:

Program.cs:

static void Main () {
    Initialize();

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault( false );

    var form = CWC.Resolve<frmMain>();
    Application.Run( form );

}

public static void Initialize ( string log4netPath = null ) {
    var container = new WindsorContainer();

    container.Kernel.ComponentModelCreated += ( s => {
        if ( s.LifestyleType == LifestyleType.Undefined )
            s.LifestyleType = LifestyleType.PerWebRequest;
    } );

    container.Install(
        new CoreManagerInstaller() , 
        new DomainInstaller() ,
        new RepositoryInstaller() ,
        new ServiceInstaller()
    );

    //Installer for MVC framework -- Must be done after other installers on its own.
    container.Install( new AppInstaller() );

    if ( log4netPath != null ) {
        //container.AddFacility( new LoggingFacility( LoggerImplementation.Log4net , log4netPath ) );
    }

    CWC.Init( container );
}

AppInstaller:

public class AppInstaller : IWindsorInstaller {

    #region IWindsorInstaller Members

    public void Install ( IWindsorContainer container , IConfigurationStore store ) {
        container.Register(
            Classes.FromThisAssembly()
                .BasedOn<CIMForm>().LifestyleTransient() ,
            Classes.FromThisAssembly()
                .BasedOn<CIMTabControl>().LifestyleTransient() ,
            Classes.FromThisAssembly()
                .BasedOn<CIMTabPage>().LifestyleTransient() ,
            Classes.FromThisAssembly()
                .BasedOn<UserControl>().LifestyleTransient() );
    }

    #endregion
}

All the above is nothing new or problematic atm.

The problem child is the UserControl i am trying to reference Interfaces form other libraries. In WebForms i would have just dropped the Property signature and started using in the Event/Methods i needed it.

As such:

public partial class ClientInformationControl : UserControl {
        public IServerRepository ServerRepository { get; set; }

        private void ClientInformation_Load ( object sender , EventArgs e ) {
            var servers = ServerRepository.Find().Select( s => new { Key=s.Id , Value=s.Name } );
            cboServers.Items.AddRange( servers.ToArray() );

        }
}

But ServerRepository never gets instantiated in this design. I have to manually call CWC.Resolve<IServerRepository>() in order for the property to have the information in need.

Is there a way to make it so that ServerRepository is automatically (auto-magically) filled with the object data from the container?

Tried doing public ClientInformationControl(IServerRepository serverRepo){} but the assignment did not persist past the constructor, so when the Control.Load event was triggered the ServerRepository Property has been emptied out.


回答1:


The problem with usercontrols is that they do no get resolved by the DI framework (DIF).

You havent posted the code of your winform, but I assume the designer code looks something like this:

private void InitializeComponent()
{
    this.ClientInformationControl1 = new ClientInformationControl();
    [...]
}

This is because you probably dragged the user control onto the form, so the DIF does not know about it.

There are multiple ways to work around this:

1: Don't use the designer to add usercontrols, but register them and let the DIF resolve them for you. You can do this by adding them to the constuctor parameters, as property, or resolve the usercontrol whenever you need it.

2: Give the parent that is resolved (the form) a IServerRepository dependency. But then you'll have to manually wire the IServerRepository into the usercontrol tho...



来源:https://stackoverflow.com/questions/21636776/how-to-use-dependency-injection-on-usercontrols-forms

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!