1

我有以下课程:

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>>

更新:我最终自己为这部分依赖项进行了类型构造。因为它们将上下文绑定与许多不受支持的泛型绑定结合在一起,所以这被证明是最干净的解决方案。

4

3 回答 3

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>());

可以在此处找到有关此方法的更多信息。

于 2012-07-11T14:19:40.750 回答
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>() });
}
于 2012-07-10T19:37:10.447 回答
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 。

于 2012-07-10T21:24:27.990 回答