Мне нужна циклическая зависимость в Виндзоре. Это сделано специально для рекурсивного подхода. Модуль A вызывает модули B-F, а модулю B требуется обратный вызов в A из-за дерева узлов.
В любом случае, я знаю, что из-за этого не могу использовать инъекцию конструктора. Итак, я настроил модуль A с внедрением свойств, чтобы получить IEnumerable ‹IModule›.
Я зарегистрировал все типы, но при разрешении модуля A Виндзор устанавливает для свойства значение 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, поскольку я регистрирую эти компоненты для стороннего инструмента.
Спасибо!
ИЗМЕНИТЬ
Чего я жду:
Windsor разрешает CompositeModule и создает экземпляр, используя ctor по умолчанию. Называет это.
Виндзор идет, чтобы удовлетворить свойство, которое является перечислимым из IModules
Он видит 6 IModules, не считая CompositeModule, и пытается создать их экземпляры в коллекции.
Он видит, что для одного из 6 модулей, CheckChildrenModule, требуется именованный экземпляр CompositeModule.
Он использует именованный экземпляр CompositeModule, созданный на шаге 1, чтобы удовлетворить зависимость ctor от CheckChildrenModule.
Теперь он может завершить сбор IModules и передать их в свойство InnerModules CompositeModule, начиная с шага 2.
Просто не знаю, как этого добиться.
IModule
свойствоInnerModules
? - person fra9001   schedule 23.07.2014