StructureMap打开通用类型

时间:2012-07-10 14:46:25

标签: c# .net dependency-injection structuremap

我有以下课程:

public interface IRenderer<T> 
{
    string Render(T obj);
}

public class Generic<T> { }

public class SampleGenericRenderer<T> : IRenderer<Generic<T>>
{
    public string Render(Generic<T> obj)
    {
        throw new NotImplementedException();
    }
}

我希望能够调用StructureMap ObjectFactory.GetInstance<IRenderer<Generic<string>>>();并获得SampleGenericRenderer<string>

我正在使用以下注册并在调用GetInstance时收到此错误。 “无法投射类型的对象:

  

ConsoleApplication1.SampleGenericRenderer'1 [ConsoleApplication1.Generic'1 [System.String]]”   输入   “ConsoleApplication1.IRenderer'1 [ConsoleApplication1.Generic'1 [System.String]。

public class CoreRegistry : Registry
{
    public CoreRegistry()
    {
        Scan(assemblyScanner =>
        {
            assemblyScanner
                .AssemblyContainingType(typeof(IRenderer<>));
            assemblyScanner.AddAllTypesOf(typeof(IRenderer<>));
            assemblyScanner
                .ConnectImplementationsToTypesClosing(
                    typeof(IRenderer<>));
        });
    }
}

有没有办法配置StructureMap,以便创建SampleGenericRenderer<string>而不是SampleGenericRenderer<Generic<string>>

更新:我最终自己为这个依赖项子集做了类型构造。因为它们将上下文绑定与许多不受支持的通用绑定相结合,所以这被证明是最干净的解决方案。

3 个答案:

答案 0 :(得分:2)

正如Pete所解释的那样,StructureMap可能无法做到这一点。其他DI容器可能会取得更大的成功,但并非所有的容器都支持更复杂的通用技巧。唯一能让我知道的是Simple Injector。使用Simple Injector,您只需要以下配置:

var container = new Container();

container.Register(typeof(IRenderer<>), typeof(SampleGenericRenderer<>));

// Usage
var renderer = container.GetInstance<IRenderer<Generic<string>>>();

renderer.Render(new Generic<string>());

有关此方法的更多信息,请访问here

答案 1 :(得分:1)

对我而言,这有效:

class Program
{
    static void Main()
    {
        ObjectFactory.Configure(x=>x.AddRegistry<CoreRegistry>());

        var instance = ObjectFactory.GetInstance(typeof(IRenderer<string>)) as IRenderer<Generic<string>>;

        var render = instance.Render(new Generic<string>());

    }
}

这会引发异常:

ObjectFactory.GetInstance<IRenderer<Generic<string>>>();

你真正的问题是什么?

编辑:

在某些情况下,这也可以起作用(如果您在设计时不知道Generic<string>):

static void Main()
{
    ObjectFactory.Configure(x => x.AddRegistry<CoreRegistry>());

    var instance = ObjectFactory.GetInstance(typeof(IRenderer<string>));
    var methodInfo = instance.GetType().GetMethod("Render");
    methodInfo.Invoke(instance, new[] { new Generic<string>() });
}

答案 2 :(得分:1)

我不相信StructureMap有任何关闭内部泛型参数的机制。

这不理想,但您可以尝试创建自己的IRegistrationConvention,每当遇到Generic<>的封闭类型时,请执行以下操作:

var generic_t = typeof(Generic<>).MakeGenericType(type);
var sample_renderer_t = typeof(SampleGenericRenderer<>).MakeGenericType(type);
var renderer_t = typeof(IRenderer<>).MakeGenericType(generic_t);
graph.AddType(renderer_t, sample_renderer_t);

有关详细信息,请参阅http://docs.structuremap.net/ScanningAssemblies.htm#section11