2011-04-12 78 views
0

我真的很喜歡StructureMap作爲IOC框架,尤其是基於約定的註冊。現在我嘗試執行以下操作:當類有一個默認(無參數)構造函數時,我想添加實現特定接口的所有類型。而這些類型必須使用這個構造函數來創建。由特定構造函數構造的結構圖addalltypesof

這是我現在註冊的正確類型,但是如何指定在創建實例時應該使用默認構造函數。

public class MyRegistry : Registry  
{ 
    public MyRegistry() 
    { 
     Scan(
      x => 
      { 
       x.AssemblyContainingType<IUseCase>(); 
       x.Exclude(t => !HasDefaultConstructor(t)); 
       x.AddAllTypesOf<IUseCase>(); 
      }); 
    } 
    private static bool HasDefaultConstructor(Type type) 
    { 
     var _constructors = type.GetConstructors(); 
     return _constructors.Any(c => IsDefaultConstructor(c)); 
    } 

    private static bool IsDefaultConstructor(ConstructorInfo constructor) 
    { 
     return !constructor.GetParameters().Any(); 
    } 
} 

回答

1

有幾種方法可以強制StructureMap使用特定的構造函數。最簡單的方法是將DefaultConstructor屬性放在要使用的構造函數上。假設你不想這樣做,你將不得不創建一個自定義RegistrationConvention。

public class UseCaseRegistrationConvention : IRegistrationConvention 
{ 
    public void Process(Type type, Registry registry) 
    { 
     if (type.IsAbstract || type.IsInterface || type.IsEnum) 
      return; 

     var useCaseInterface = type.GetInterface("IUseCase"); 
     if (useCaseInterface == null) 
      return; 

     var constructor = type.GetConstructors().FirstOrDefault(c => !c.GetParameters().Any()); 
     if (constructor != null) 
     { 
      registry.For(useCaseInterface).Add(c => constructor.Invoke(new object[0])); 
     } 
    } 
} 

然後在您的掃描呼叫時使用:

Scan(x => 
    { 
     x.AssemblyContainingType<IUseCase>(); 
     x.With(new UseCaseRegistrationConvention()); 
    });