如何在用户控件中使用依赖注入;形式

时间:2014-02-07 20:04:14

标签: winforms dependency-injection castle-windsor

遇到知识差距,离开WinForms已经很久了,不确定我是否正在为温莎城堡做这件事。

在过去的5年里,我开发了ASP.Net应用程序(WebForms,MVC等)。我现在有一个项目,其中Web界面不是一个可行的解决方案。所以我们正在使用WinForms。

使用Asp.Net,我会设置Castle Windsor容器,CWC,静态类,并且所有事情都可以自行处理依赖注入等。

对于WinForms,我遇到了一些问题。我显然无法实现与WebForms开发相同的依赖注入规则。

当前实施:

的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
}

以上所有内容都不是新的或有问题的。

问题孩子是UserControl我试图引用其他库的接口。在WebForms中,我会删除Property签名并开始在我需要的事件/方法中使用。

因此:

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() );

        }
}

ServerRepository永远不会在此设计中实例化。我必须手动调用CWC.Resolve<IServerRepository>()才能让财产获得有需要的信息。

有没有办法让ServerRepository自动(自动地)用容器中的对象数据填充?

尝试执行public ClientInformationControl(IServerRepository serverRepo){}但是赋值没有持续超过构造函数,因此当触发Control.Load事件时,ServerRepository属性已被清空。

1 个答案:

答案 0 :(得分:1)

usercontrols的问题在于它们没有被DI框架(DIF)解决。

您尚未发布winform的代码,但我认为设计器代码看起来像这样:

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

这是因为您可能将用户控件拖到表单上,因此DIF不知道它。

有多种方法可以解决这个问题:

1:不要使用设计器来添加用户控件,而是注册它们并让DIF为您解决它们。您可以通过将它们作为属性添加到constuctor参数中来执行此操作,或者在需要时解析用户控件。

2:为已解析的父级(表单)提供IServerRepository依赖项。但是你必须手动将IServerRepository连接到用户控件......

相关问题