Dependency injection 使用Castle Windsor子容器解析具有特定实例的类型

Dependency injection 使用Castle Windsor子容器解析具有特定实例的类型,dependency-injection,castle-windsor,Dependency Injection,Castle Windsor,我目前正在使用Castle Windsor的子容器功能在工厂方法中覆盖特定类型与特定实例的注册。我使用子容器纯粹是为了使注册对于单个解决方案是临时的——换句话说,我不希望注册影响该类型的所有解决方案 也许一些代码可以解释我的意思 我有一个Func,它充当工厂Func——我给它一个IReportCategory的实现,它返回一个IReportCategoryViewModel的新实例。(IReportCategoryViewModel依赖于IReportCategory) 这在温莎城堡登记如下:

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

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

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

这在温莎城堡登记如下:

        container.Register(
            Component.For<Func<IReportCategory, IReportCategoryViewModel>>().Instance(
                category => ResolveCategoryViewModelFactory(container, category)));
    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>();
        }
    }
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);
    }
    ...
上述方法实现的是IReportCategoryViewModel的解析,将IReportCategory的特定实例作为依赖项注入。如果IReportCategoryViewModel有其他需要满足的依赖项,那么容器会自动注入这些依赖项

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

        container.Register(
            Component.For<Func<IReportCategory, IReportCategoryViewModel>>().Instance(
                category => ResolveCategoryViewModelFactory(container, category)));
    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>();
        }
    }
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);
    }
    ...
公共类测试
{
私有只读功能工厂;
公共测试(Func工厂)
{
这个工厂=工厂;
}
公共测试()
{
//创建一个类别(注意:这可能以某种方式从容器中解决)
IReportCategory=新的ReportCategory();
//调用工厂以解析视图模型
IReportCategoryViewModel vm=工厂(类别);
}
...
问题:这似乎是一件合适的事情吗?从我得到的印象来看,温莎城堡不推荐儿童容器-有没有其他方法可以达到同样的效果


感谢您的帮助。

当然还有更好的方法,而且您现在使用的代码有一个bug-当您处置子容器时,它将尝试释放您正在解析的所有组件实例,因此在您有机会使用它们之前,它们可能不可用(已处置)


如果我正确理解了您的解释,那感觉就像是一份工作。

按照Krzysztof的建议使用类型化工厂,下面是我如何实现上述功能的。它比使用子容器简单得多

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

public interface ICategoryViewModelFactory
{
    CategoryViewModel Create(ReportCategory category);
} 
接下来,确保容器中启用了
TypedFactoryFacility

container.AddFacility<TypedFactoryFacility>();
container.Register(
    Component.For<ICategoryViewModelFactory>()
        .AsFactory());
警告:工厂方法中的参数名称需要与工厂创建的对象的构造函数的参数名称匹配。在上例中,工厂接口定义了方法:

CategoryViewModel Create(ReportCategory category)
CategoryViewModel
的构造函数还必须具有名为“category”的参数:

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

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

类型化工厂确实是一种更好的方法!非常感谢Krzysztof!这不会产生与子容器相同的行为-因为它使用名称将构造函数参数与工厂方法参数相匹配,它只对工厂本身返回的类型有效,这意味着它的任何依赖项都不会得到如果需要注入实例,实例会传递给工厂方法)感谢您发布用于解决此问题的代码-我花了很长时间寻找这样一个示例来帮助我。但是我仍然感到困惑,希望您能提供帮助。我已经有效地复制了您的代码并替换了一些单词,使其适合我的对象,当我运行应用程序时,我得到了一个
DependencyResolverEx异常
针对与您的
ReportCategory
对象等价的我的异常。异常说明我的视图模型依赖于无法解决的模型。您是否在Castle Windsor注册了
ReportCatgory