2012-06-19 68 views
0

我有一个使用MVP模式的Windows窗体应用程序。每个视图都是一个WinForms用户控件,并由处理非UI关注的演示者支持。该应用程序使用Castle Windsor,所有视图演示者和许多其他组件都通过Windsor Container解决。在温莎城堡为Windows窗体自定义属性注入

我希望能够做的是为用户控件视图自定义属性注入。我的观点并没有大量使用财产注入,但它偶尔非常有用,效果很好。问题是,我的用户控件通常包含嵌套控件,而嵌套控件又可以包含其他嵌套控件,而属性注入不适用于这些嵌套控件,因为它们不是通过容器直接解析的。

我想要做的是为继承自SWF Control类的组件配置属性注入。除了在组件上查找属性之外,我还希望在嵌套控件(在Controls)集合中找到属性,并注入这些嵌套属性。

我知道温莎城堡是非常灵活和可配置的,所以这可能是可能的。尽管我需要朝正确的方向推动。这可能吗?有没有人试图做类似的事情?

+0

它很安静,我可以听到蟋蟀。这必须是其他人不想做的事情,没有人应该尝试去做,或者做不到的事情。 –

+0

如果你想Windsor管理嵌套控件的依赖关系,为什么不让Windsor管理它们,包括创建它们? – kko

+0

我正在讨论作为InitializeComponent方法的一部分创建的嵌套控件,其中构造了由设计器创建的所有控件。我仍然希望能够使用WinForms设计器来构建我的用户控件。正是这些控件我希望能够注入依赖。实际上,将这些属性视为属于外部用户控件。 –

回答

1

如果我已经正确理解你的问题,我认为实现你想要的东西的唯一方法是通过某种可怜的人的依赖注入(有争议的 - 请不要投票给我!)因为Winforms设计师生成一种构建您所说的各种子控件的方法,这对IoC来说显然是不可靠的。

我不知道你将能够做财产注入,但你可以利用的构造,这里是一个头发右脑方案我刚刚炮制...

首先,创建一些方式来访问你的温莎容器 - 这样的事情可能会做的伎俩:

public static class MyContainer 
{ 
    private static readonly IWindsorContainer _container = Bootstrap(); 

    // I did it like this so that there is no explicit dependency 
    // on Windsor - this would be the only place you need to change 
    // if you want an alternate container (how much you care about 
    // that is up to you) 
    public static T Resolve<T>() 
    { 
     return _container.Resolve<T>(); 
    } 

    private static IWindsorContainer Bootstrap() 
    { 
     var container = new WindsorContainer(); 
     container.Install(FromAssembly.This()); 

     // ... whatever else you need to do here 

     return container; 
    } 
} 

其次,在内部控制,要将一些属性注入做这样的事情(我去了好醇” ILogger作为东西的例子中,你可能想要注射):

public partial class MyFancyControl : UserControl 
{  
    // Constructor to keep the winforms designer happy 
    public MyFancyControl() 
     : this (MyContainer.Resolve<ILogger>()) 
    { 
     // Intentionally always blank as this 
     // is an un-unit-testable method 
    } 

    // Constructor that does the actual work 
    public MyFancyControl(ILogger logger) 
    { 
     InitializeComponent(); 
     Logger = logger; 
    } 

    public ILogger Logger { get; private set; } 
} 

注意:使用记录器会引发一对明显的气味 - 有时候您根本没有在容器中注册这样一个组件(通常您有一个空记录器),因此您可能需要连接某种形式的机制,但如果你需要或不需要,我会留给你。

+0

感谢您的回复。它使用可怕的服务定位器模式,但它会起作用。这里一个重要的考虑是你必须明确地释放你以这种方式解决的任何组件,否则你会得到内存泄漏,至少对于非单件组件。释放它的地方将在Dispose()方法中。要记住组件是否通过容器解决了,变得更加复杂。是的,它会工作,但我想知道是否有更好的方式使用温莎城堡的“内脏”保持跟踪。 –

+0

我只是有一个想法:你可以使用类型化的工厂设施:以上述方式传递工厂,然后使用工厂来获得你需要的任何方式Windsor将控制从工厂解决事情的发布政策: http://stw.castleproject.org/Windsor.Typed-Factory-Facility-interface-based-factories.ashx - 你可能不得不弯曲你的架构,以使工厂看起来合理,虽然这看起来合理 - 有一系列释放工厂创建的组件的方法 - 可能不会比释放frm – kmp

+0

有趣的想法更好。我会看看它是否适用于我,我会让你知道。 –