2015-10-26 116 views
0

StructureMap 4構造函數依賴我想用StructureMap 4.
我創建了一個接口IDeveloper和兩個實現
CSharpDeveloper這是裝飾類型,DeveloperDecorator
這是裝飾落實decorator pattern
裝飾類型對IDeveloper有依賴關係,類本身實現了IDevloper,這意味着其中一個類型應該是一個命名實例。
命名實例是CSharpDeveloper與命名實例

public interface IDeveloper 
{ 
} 

public class CSharpDeveloper : IDeveloper 
{ 
} 

public class DeveloperDecorator : IDeveloper 
{ 
    private readonly IDeveloper developer = null; 

    public DeveloperDecorator(IDeveloper developer) { 
     this.developer = developer; 
    } 
} 

我想註冊的DeveloperDecorator爲IDeveloper,我可以使用未命名的GetInstance重載函數解析式

container.GetInstance<IDeveloper>(); 

和StructureMap將能夠解決的依賴鍵入爲命名實例。像這樣的(概念驗證代碼)的東西

Func<IDeveloper> factory =() => { 
    return new DeveloperDecorator(container.GetInstance<IDeveloper>("name")); 
};    

我不能在所有使用泛型,所以我不能使用Ctor<TCtorType>() API。
我有一個名爲TypeMap的類型,它包含服務類型,具體類型和可選名稱。

public class TypeMap 
{ 
    public string Name { get; set; } 
    public Type ServiceType { get; set; } 
    public Type ConcreteType { get; set; } 
} 

我試過使用依賴但沒有任何工作。

public void Register(TypeMap typeMap, ITypeMapCollection dependencies = null) { 
    container.Configure(x => { 
     var use = x.For(typeMap.ServiceType) 
        .Add(typeMap.ConcreteType); 

     if (typeMap.Name.IsNotNullOrEmpty()) { 
      use.Named(typeMap.Name); 
     } 

     if (dependencies.IsNotNullOrEmpty()) { 
      dependencies.ForEach(dependency => { 
       use.Dependencies.Add(dependency.Name, dependency.ServiceType); 
      }); 
     } 
    }); 
} 

謝謝。

回答

0

我已經設法通過提供Use方法來創建實例並解析容器的所有依賴關係。

public void Register(TypeMap typeMap, ITypeMapCollection dependencies = null) { 
    container.Configure(x => { 
     var use = x.For(typeMap.ServiceType) 
        .Use(typeMap.ConcreteType); 

     if (typeMap.Name.IsNotNullOrEmpty()) { 
      use.Named(typeMap.Name); 
     } 

     if (dependencies.IsNotNullOrEmpty()) { 
      x.For(typeMap.ServiceType).Use("composite", BuildExpression(typeMap, dependencies)); 
     } 
    }); 
} 

private Func<IContext, object> BuildExpression(TypeMap typeMap, ITypeMapCollection dependencies) { 
    var contextParameter = Expression.Parameter(typeof(IContext), "context"); 
    var @params = dependencies.ToArray(d => d.ServiceType); 
    var ctorInfo = typeMap.ConcreteType.GetConstructor(@params); 
    var genericMethodInfo = typeof(IContext).GetMethods().First(method => { 
     return method.Name.Equals("GetInstance") && 
       method.IsGenericMethodDefinition && 
       method.GetParameters().Length == 1; 
    }); 

    var getInstanceCallExpressions = dependencies.Select(dependency => { 
     var nameParam = Expression.Constant(dependency.Name, typeof(string)); 
     var methodInfo = genericMethodInfo.MakeGenericMethod(new[] { dependency.ServiceType }); 

     return Expression.Call(contextParameter, methodInfo, new[] { nameParam }); 
    }); 

    var lambda = Expression.Lambda<Func<IContext, object>>(
        Expression.New(ctorInfo, getInstanceCallExpressions), 
        contextParameter); 

    return lambda.Compile(); 
}