通过Castle Windsor的属性注入循环依赖

时间:2014-07-23 15:06:05

标签: c# recursion dependency-injection castle-windsor property-injection

我需要Windsor中的循环依赖。这是针对递归方法的目的。模块A调用模块B-F,模块B由于节点树而需要回调到A.

无论如何,我知道我不能因为这个而使用构造函数注入。因此,我设置了带有属性注入的模块A,以获得IEnumerable< IModule&gt ;.

我已经注册了所有类型但是在解析模块A时,Windsor正在使用Null设置属性(我让它抛出异常)。我尝试使用DependsOn,但这似乎只适用于构造函数参数。

我怎样才能让Windsor通过属性注入将我的模块B-F集合解析到模块A中,这样我就可以拥有我需要的依赖循环?

这是顶级模块(模块A)和IModule;

public interface IModule
{
    bool IsAccessibleToUser(INode node);
}

public class CompositeModule:IModule
{
    private IEnumerable<IModule> innerModules;

    public IEnumerable<IModule> InnerModules
    {
        get { return innerModules; }
        set { 
            if (null == innerModules) throw new ArgumentNullException("innerModules");
            innerModules = value;
        }
    }

    public CompositeModule()
    {
        InnerModules = new List<IModule>();
    }


    public bool IsAccessibleToUser(INode node)
    {
        return innerModules.All(module => module.IsAccessibleToUser(node));
    }

}

递归子模块:

public class CheckChildrenModule : IModule
{

    private IModule compositeModule;

    public CheckChildrenModule(IModule compositeModule)
    {

        if (null == compositeModule) throw new ArgumentNullException("compositeModule");

        this.compositeModule = compositeModule;

    }

    public bool IsAccessibleToUser(INode node)
    {

        var attributes = node.Attributes;

        if (!attributes.ContainsKey("checkchildren")) return true;

        string checkchildren = attributes["checkchildren"].ToString();

        if (checkchildren.ToLower() == bool.TrueString.ToLower())
        {
            //look for any child with result of TRUE and stop immediately if found in order to be efficient.
            return node.ChildNodes.Any(childNode => compositeModule.IsAccessibleToUser(childNode));
        }

        return true; //check false or some other value. return true!

    }
}

我的注册:

// Configure Windsor to resolve arrays in constructors
container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel, true));
//collections too
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));

//other stuff here

container.Register(Component.For<IModule>()
            .ImplementedBy<CompositeModule>()
            .Named("CompositeModule1"));

container.Register(Component.For<IModule>().ImplementedBy<CheckChildrenModule>()
            .DependsOn(ServiceOverride.ForKey<IModule>().Eq("CompositeModule1")));

//A few other IModules here, all of which should be passed to the Composite Module "innerModules" property.

正如我所说,我尝试了DependsOn,它似乎不适用于属性,还有PropertyRequire,它没有效果,我仍然传递了null。

请注意,我无法访问Container.Resolve代码,因为我正在为第三方工具注册这些组件。

谢谢!

修改

我的期望:

  1. Windsor解析CompositeModule并使用默认ctor创建实例。命名为。

  2. 温莎去满足属性,这是一个可以容纳的IModules

  3. 它看到6个IModules,不计算CompositeModule,并尝试将它们实例化为集合

  4. 它看到6个模块之一CheckChildrenModule需要CompositeModule的命名实例。

  5. 它使用在步骤1中创建的CompositeModule的命名实例来满足对CheckChildrenModule的ctor依赖

  6. 现在它可以完成IModules的收集,并将它们从第2步传递到CompositeModule的InnerModules属性。

  7. 只是不知道如何让它发生。

1 个答案:

答案 0 :(得分:4)

我相信你可以使用构造函数注入的延迟解决方案来实现循环依赖。

container.Register(Component.For<ILazyComponentLoader>()
                            .ImplementedBy<LazyOfTComponentLoader>());

public class CompositeModule : ICompositeModule
{
    private IEnumerable<IModule> _childModules;
    public CompositeModule(IEnumerable<IModule> childModules) 
    {
        _childModules = childModules;
    }
}

public class CheckChildrenModule : IModule
{
    private Lazy<ICompositeModule> _compositeModule;
    public CheckChildrenModule(Lazy<ICompositeModule> compositeModule)
    {
        _compositeModule = compositeModule;
    }

    public void DoStuff() 
    {
        _compositeModule.Value.DoStuff();
    }
}