2012-03-05 75 views
3

我使用StructureMap 2.6,並試圖使用Decorator模式Decorator模式:與structuremap 2.6

 For<IBusRefTranslator>().Use<BusRefTranslator>() 
      .EnrichWith((x) => new LoggingBusRefTranslator(x)) 
      .Ctor<string>("connectionString").Is(connectionString); 

這完美的作品,但我LoggingBusRefTranslator有需要解決的依賴關係,所以我想StructureMap建立它。我無法弄清楚正確的路線和豐富的大多數例子,我可以使用舊的語法。

回答

2

我已經設法通過移動我的所有依賴我的裝飾來構造依賴和使用EnrichWith延伸的另一種形式來解決這個問題:

 For<IBusRefTranslator>().Use<BusRefTranslator>() 
      .EnrichWith<IBusRefTranslator>((c, x) => new LoggingBusRefTranslatorDecorator(x, c.GetInstance<IFusionLogService>())) 
      .Ctor<string>("connectionString").Is(connectionString); 
3

我已經寫了下面的擴展方法解決了這個自己。優點是配置的語法更簡單,並且裝飾器的依賴關係自動注入,而不必在new語句中自己處理它們。用於裝飾的對象是作爲語法如下:

For<IBusRefTranslator>().Use<BusRefTranslator>() 
    .Decorate().With<LoggingBusRefTranslatorDecorator>(); // dependencies and decoratee automatically injected 

擴展類:

public static class StructureMapExtensions 
{ 
    /// <summary> 
    /// Configures the defined instance to be wrapped by an instance of another decorator type 
    /// </summary> 
    public static DecorateConfig<T> Decorate<T>(this SmartInstance<T> instance) 
    { 
     return new DecorateConfig<T>(instance); 
    } 

    public class DecorateConfig<T> 
    { 
     private readonly SmartInstance<T> _instance; 
     internal DecorateConfig(SmartInstance<T> instance) 
     { 
      _instance = instance; 
     } 

     private static IEnumerable<Type> GetTypeAndAllBaseTypes(Type t) 
     { 
      if (t == typeof(object)) 
       yield break; 

      yield return t; 

      foreach (var @base in t.GetInterfaces().Union(GetTypeAndAllBaseTypes(t.BaseType))) 
       yield return @base; 
     } 

     private static string FindArgumentNameForWrappedInner(Type decoratorType) 
     { 
      foreach (var t in GetTypeAndAllBaseTypes(typeof(T))) 
      { 
       var argumentName = new Plugin(decoratorType).FindArgumentNameForType(t, CannotFindProperty.Ignore); 
       if (argumentName != null) 
        return argumentName; 
      } 

      throw new ConfigurationErrorsException("Type " + decoratorType + " has no constructor arguments of type " + typeof(T)); 
     } 

     public SmartInstance<TDecorator> With<TDecorator>() 
     { 
      var decoratorInstance = new SmartInstance<TDecorator>(); 
      _instance.EnrichWith((context, inner) => decoratorInstance 
       .WithCtorArg(FindArgumentNameForWrappedInner(typeof(TDecorator))).EqualTo(inner) 
       .Build(typeof (TDecorator), (BuildSession) context)); 

      return decoratorInstance; 
     } 
    }