2012-10-26 58 views
2

也許抽象類型的工廠並不是一個從溫莎開始的簡單點(2.5.3如果它很重要),但我必須這樣做。 我想建立一個工廠根據消息類型給回處理器。到目前爲止,我已經從不同的地方清除以下代碼:在Windsor的通用打字工廠

public class Complicato 
{ 
    public static void Do(string[] args) 
    { 
     IKernel kernel = new DefaultKernel(); 
     IWindsorContainer container = new WindsorContainer(); 

     kernel.AddFacility<TypedFactoryFacility>(); 

     container.Install(); 
     container.Register(

      Component.For<HandlerSelector, ITypedFactoryComponentSelector>(), 

      AllTypes.FromThisAssembly().BasedOn(typeof(ITrier<>)) 
       .WithService.Base().Configure(conf => conf.LifeStyle.Is(LifestyleType.Transient)), 
      Component.For<Factor>(), 
      Component.For<ITryFactory>().AsFactory(c => c.SelectedWith<HandlerSelector>()).LifeStyle.Singleton); 

     var factor = container.Resolve<Factor>(); 
     var factory = container.Resolve<ITryFactory>(); 
    } 
} 

public class HandlerSelector : DefaultTypedFactoryComponentSelector 
{ 
    protected override Type GetComponentType(MethodInfo method, object[] arguments) 
    { 
     return typeof(ITrier<>).MakeGenericType(arguments[0].GetType()); 
    } 
} 

public class Factor 
{ 
    private ITryFactory factory; 

    public void Try(IWhat onto) 
    { 
     factory.GetTrier(onto).Try(onto); 
    } 
} 


public interface ITryFactory 
{ 
    ITrier<IWhat> GetTrier(IWhat onto); 
    void Release(object elem); 
} 


public interface IWhat { } 


public interface ITrier<in TWhat> where TWhat : IWhat 
{ 
    void Try(TWhat input); 
} 


public class TrierYes : ITrier<WhatYes> 
{ 
    public void Try(WhatYes input) { Console.WriteLine("Yes? " + input.Aye()); } 
} 

public class TrierNo : ITrier<WhatNot> 
{ 
    public void Try(WhatNot input) { Console.WriteLine("No? " + input.Naa()); } 
} 

public class WhatYes : IWhat 
{ 
    public bool Aye() { return true; } 
} 

public class WhatNot : IWhat 
{ 
    public bool Naa() { return false; } 
} 

這裏的主要問題是,id不起作用。首先,我得到了工廠爲null的Factor,結果試圖解決工廠明確地給我ComponentActivator:無法代理Factories.Complex.ITryFactory與內部消息的攔截器Castle.TypedFactory.Interceptor無法解析和「Keys(組件使用特定的鍵) - 容器中未註冊的Castle.TypedFactory.Interceptor。我甚至不知道Handler選擇器是否工作,到目前爲止還沒有問題。

如果我讓ITrier不是通用的 - 它突然開始工作,但它絕對不是我想要實現的。

那麼,我該如何讓一些愚蠢的初學者在溫莎配置中犯錯或者誤解了打字工廠的想法?

爲了完整起見,這裏的異常消息:

Castle.MicroKernel.ComponentActivator.ComponentActivatorException was unhandled 
    Message=ComponentActivator: could not proxy Factories.Complex.ITryFactory 
    Source=Castle.Windsor 
    StackTrace: 
     at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, Object[] arguments, Type[] signature) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel\ComponentActivator\DefaultComponentActivator.cs:line 166 
    InnerException: Castle.MicroKernel.Resolvers.DependencyResolverException 
     Message=The interceptor Castle.TypedFactory.Interceptor could not be resolved 
     Source=Castle.Windsor 
     StackTrace: 
      at Castle.Core.InterceptorReference.Castle.MicroKernel.IReference<Castle.DynamicProxy.IInterceptor>.Resolve(IKernel kernel, CreationContext context) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\Core\InterceptorReference.cs:line 142 

回答

2

與獲獎者是

container.AddFacility<TypedFactoryFacility>(); // good code 

,而不是

kernel.AddFacility<TypedFactoryFacility>(); // bad code 

現在我只有不注入工廠的問題和不正確的HandlerSelector。

NullReference通過引入顯式初始化構造函數來解決。我不知道爲什麼我認爲它沒有工作。

處理程序界面的最終版本如下:

public interface ITrier<out TWhat> where TWhat: IWhat 
{ 
    void Try(IWhat input); 
} 

要允許協方差。不要超級優雅,因爲要求不必要的演員和處理者放鬆他們的類型。但這是殘酷的現實。你要麼是共同的,要麼是反變形的。