【问题标题】:Using Castle Windsor child containers to resolve a type with a specific instance使用 Castle Windsor 子容器来解析具有特定实例的类型
【发布时间】:2011-11-10 19:25:56
【问题描述】:

我目前正在使用 Castle Windsor 的子容器功能来覆盖使用工厂方法中的特定实例注册特定类型。我纯粹使用子容器,以便注册对于单个解决方案是临时的 - 换句话说,我不希望注册影响该类型的所有解决方案。

也许一些代码可以解释我的意思。

我有一个 Func,它充当工厂 Func<IReportCategory, IReportCategoryViewModel> - 我给它一个 IReportCategory 的实现,它返回一个 IReportCategoryViewModel 的新实例。 (IReportCategoryViewModel 依赖于 IReportCategory)。

在温莎城堡注册如下:

        container.Register(
            Component.For<Func<IReportCategory, IReportCategoryViewModel>>().Instance(
                category => ResolveCategoryViewModelFactory(container, category)));

其中ResolveCategoryViewModelFactory的实现方式如下:

    private CategoryViewModel ResolveCategoryViewModelFactory(IWindsorContainer container, IReportCategory category)
    {
        using (IWindsorContainer childContainer = new WindsorContainer())
        {
            childContainer.Register(Component.For<IReportCategory>().Instance(category));
            container.AddChildContainer(childContainer);

            return childContainer.Resolve<IReportCategoryViewModel>();
        }
    }

上述方法实现的是IReportCategoryViewModel的解析,将IReportCategory的具体实例作为依赖注入。如果 IReportCategoryViewModel 有其他需要满足的依赖项,那么这些依赖项会被容器自动注入。

我随后可以按如下方式使用 Func:

public class Test
{
    private readonly Func<IReportCategory, IReportCategoryViewModel> factory;

    public Test(Func<IReportCategory, IReportCategoryViewModel> factory)
    {
        this.factory = factory;
    }

    public void ResolveTest()
    {
        // Create a category (note: this would probably be resolved from the container in some way)
        IReportCategory category = new ReportCategory();

        // Call into the factory to resolve the view model
        IReportCategoryViewModel vm = factory(category);
    }
    ...

问题:这看起来是否合适?从我得到的印象来看,温莎城堡不推荐使用子容器——还有其他方法可以达到同样的效果吗?

感谢您的帮助。

【问题讨论】:

    标签: dependency-injection castle-windsor


    【解决方案1】:

    按照 Krzysztof 的使用 Typed Factories 的建议,以下是我实现上述功能的方法。它比使用子容器要简单得多!

    首先,创建一个定义工厂方法签名的工厂接口:

    public interface ICategoryViewModelFactory
    {
        CategoryViewModel Create(ReportCategory category);
    } 
    

    接下来,确保在容器中启用TypedFactoryFacility

    container.AddFacility<TypedFactoryFacility>();
    

    最后向容器注册工厂接口:

    container.Register(
        Component.For<ICategoryViewModelFactory>()
            .AsFactory());
    

    现在您可以将ICategoryViewModelFactory 注入到您的类中,并调用Create() 方法来创建CategoryViewModel 的新实例:

    public class SomeClass
    {
        public SomeClass(ICategoryViewModelFactory categoryViewModelFactory)
        {
            // This would probably be resolved by the container (it's like this for the example)
            ReportCategory category = new ReportCategory();
    
            // Get Windsor to resolve the view model using the factory
            ReportCategoryViewModel vm = categoryViewModelFactory.Create(category);
    
            ....
    

    警告:工厂方法中的参数名称需要与工厂创建的对象的构造函数的参数名称匹配。在上面的例子中,工厂接口定义了方法:

    CategoryViewModel Create(ReportCategory category)
    

    CategoryViewModel 的构造函数还必须有名为“category”的参数:

    public CategoryViewModel(ReportCategory category)
    

    这是因为工厂方法等价于以下:

    container.Resolve<CategoryViewModel>(new { category = paramPassedIntoFactoryMethod });
    

    【讨论】:

    • 感谢您发布用于解决此问题的代码 - 我花了很长时间寻找这样的示例来帮助我。但是我仍然卡住了,希望你能提供帮助。我已经有效地复制了您的代码并替换了一些单词以使其适合我的对象,当我运行应用程序时,我得到一个 DependencyResolverException 与您的 ReportCategory 对象等效。异常表明我的视图模型依赖于无法解析的模型。你有ReportCatgory 在温莎城堡注册吗?如果有,怎么做?
    • 我设法让它工作并在以下问题上发布了我的代码:stackoverflow.com/a/11604109/336752
    【解决方案2】:

    绝对有更好的方法,而且您现在使用的代码有一个错误 - 当您处置子容器时,它会尝试释放您正在解析的所有组件实例,因此它们可能无法使用(处置)在您甚至有机会使用它们之前。

    如果我正确理解你的解释,那感觉就像 typed factories 的工作。

    【讨论】:

    • 类型化工厂确实是一种更好的方法!非常感谢 Krzysztof!
    • 这不会导致与子容器完全相同的行为 - 因为它使用名称将构造函数参数与工厂方法参数匹配,它仅适用于工厂本身返回的类型,这意味着如果需要注入,它的任何依赖项都不会将实例传递给工厂方法。这是我一直用来探索这个的要点(这可能会更好地解释:))gist.github.com/1357829
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 2012-06-06
    相关资源
    最近更新 更多