【问题标题】:StructureMap 4 constructor dependency with named instance具有命名实例的 StructureMap 4 构造函数依赖项
【发布时间】:2015-10-26 21:50:59
【问题描述】:

我想使用 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&lt;TCtorType&gt;() 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);
            });
        }
    });
}

谢谢。

【问题讨论】:

    标签: c# ioc-container structuremap constructor-injection


    【解决方案1】:

    我已经通过为 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();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多