繁体   English   中英

温莎城堡通过属性注入产生的循环依赖性

[英]Cyclic dependency via property injection in Castle Windsor

我在温莎需要一个周期性的依赖。 这是为了递归方法。 模块A调用由于节点树,模块BF和模块B需要回调回A。

无论如何,因此我知道我不能使用构造函数注入。 因此,我使用属性注入设置了模块A,以获得IEnumerable <IModule>。

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

如何通过属性注入使Windsor将我的模块BF集合解析为模块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个IModule,不计算CompositeModule,并尝试将它们实例化为一个集合

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

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

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

只是不知道如何使它发生。

我相信您可以在构造函数注入中使用惰性解析来实现循环依赖。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM