我想使用StructureMap 4实现decorator pattern
我创建了一个界面IDeveloper
和两个实现
CSharpDeveloper
是装饰类型,DeveloperDecorator
这是装饰者。
装饰器类型依赖于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 :(得分: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();
}