2011-12-13 3 views
1

У меня есть домен, который выглядит примерно так:Castle.Windsor: Условно разрешения дополнительной реализация

public interface IParent{ IChild[] Children { get; set; } } 

public class Parent1 : IParent 
{ 
    public IChild[] Children { get; set; } 
    public Parent1(IChild[] children) { Children = children; } 
} 

public class Parent2 : IParent 
{ 
    public IChild[] Children { get; set; } 
    public Parent2(IChild[] children) { Children = children; } 
} 

public interface IChild{} 
public class Child1 : IChild{} 
public class Child2 : IChild{} 

я использую ArrayResolver получить несколько детей для родителей решенных. Что мне нужно иметь, что когда я решаю Parent1 я получаю только Child1 осуществления (возможно, некоторые другие, которые всегда присутствуют) , но когда я решаю Parent2 я хочу добавить Child2.

Моя первая попытка была такова:

[TestFixture] 
public class BasicUnderstandingTests 
{ 
    [Test] 
    public void CanAddImplementationInOverride() 
    { 
     var container = new WindsorContainer(); 

     container.Kernel.Resolver 
       .AddSubResolver(new ArrayResolver(container.Kernel)); 

     container.Register(Component 
      .For<IParent>().ImplementedBy<Parent1>()); 
     container.Register(Component 
      .For<IParent>().ImplementedBy<Parent2>().Named("Parent2") 
      .ServiceOverrides(ServiceOverride.ForKey<IChild>().Eq<Child2>())); 

     container.Register(Component 
      .For<IChild>().ImplementedBy<Child1>()); 
     container.Register(Component 
      .For<IChild>().ImplementedBy<Child2>()); 


     var p1 = container.Resolve<IParent>(); 
     Assert.IsAssignableFrom<Parent1>(p1); 
     Assert.AreEqual(1, p1.Children.Length); 

     var p2 = container.Resolve<IParent>("Parent2"); 
     Assert.IsAssignableFrom<Parent2>(p2); 
     Assert.AreEqual(2, p2.Children.Length); 
    } 
} 

Но это терпит неудачу на первом утверждают, если оба Реализации если IChild регистрируются и на втором утверждают, если только первая реализация зарегистрирована.

Есть ли элегантный способ сделать это, что мне не хватает?

+0

Не должно быть p2.Children.Length быть 1, поскольку вы зарегистрировали только один «Child2»? – PatrickSteele

+0

Нет, дело в том, что у родителя 1 есть только 1 ребенок и родитель 2 ребенка (Child1 и Child2). –

ответ

1

Хорошо, это крупный взлом , но это был забавный маленький проект. Я создал обычай ISubDependencyResolver, чтобы справиться с этой ситуацией (вроде). Вместо ArrayResolver, попробуйте это один:

public class ParentChildResolver : ISubDependencyResolver 
{ 
    private readonly IKernel kernel; 

    public ParentChildResolver(IKernel kernel) 
    { 
     this.kernel = kernel; 
    } 

    public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) 
    { 
     var number = model.Name.Substring(model.Name.Length - 1, 1); 
     var childType = Type.GetType(String.Format("{0}.Child{1}", model.Service.Namespace, number)); 
     var children = kernel.ResolveAll<IChild>().Where(c => childType.IsAssignableFrom(c.GetType())).ToArray(); 
     return children; 
    } 

    public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency) 
    { 
     return typeof (IChild[]).IsAssignableFrom(dependency.TargetType); 
    } 
} 

Она имеет несколько основных предположений, что делает его действительно Hacky:

  1. Он работает только для типов, названных «Parent1» через «Parent9» (так его только соответствует «Child1» через «Child9»).
  2. Предполагается, что реализации Child находятся в том же пространстве имен, что и реализации родителя (что может не сработать для вас).
  3. Нет ошибок!

Вы также можете избавиться от служебного переопределения, поскольку он ничего не делал.

Я не мог придумать более простой способ сделать это, так как ядро ​​видит все дочерние объекты как объекты IChild. Вам нужно увидеть, реализуются ли те объекты IChild определенным типом для родителя, и я сопоставлял их с суффиксом числа.

Как я уже сказал - крупный взлом. :)

+0

Это не совсем решение моей проблемы (см. Мой ответ на ваш комментарий), но с некоторыми изменениями я думаю, что я получу что-то подобное, чтобы работать. –

Смежные вопросы