为与StructureMap实现某些接口的所有类型注册开放泛型类型

时间:2011-07-25 10:50:51

标签: structuremap open-generics

我想注册实现IManager的所有类型,以便它们可以用作通用T类的Lazy<T>类型。

例如:

public TetraRadioPropertyUpdater(Lazy<IRadioManager> lazyRadioManager)

我使用自制扫描仪,因为我的具体类型和接口是内部的,因此我无法使用内置的StructureMap扫描机制。

在循环的第一个语句中注册我的所有IManager类型,如For<IRadioManager>().Singleton().Use<RadioManager>()

同样,我希望它们被注册,以便它们可以用作Lazy<T>的通用类型,如For<Lazy<IRadioManager>().Use<Lazy<RadioManger>>()

 InterfaceScanner<IManager> interfaceScanner = new InterfaceScanner<IManager>();

 // managerMapping looks like:
 // { IRadioManager, RadioManager }
 // { ICallManager, CallManager }
 // .. more manager interface to plugin type pairs  
 foreach (KeyValuePair<Type, Type> managerMapping in interfaceScanner.Process())
 {
    // the key is the plugin type, value is the concrete type
    For(managerMapping.Key).Singleton().Use(managerMapping.Value);

    // something like this.. ?
    For(typeof(Lazy<>)).Singleton().Use(c => new Lazy(() => c.GetInstance(managerMapping.Value)));
 }

这可能吗?我如何为StructureMap配置它?

1 个答案:

答案 0 :(得分:2)

UPDATE: StructureMap v3实现了这个开箱即用的功能,因此不再需要这个技巧。


您可以显式注册这样的类:

container = new Container(x =>
{
    x.Scan(y =>
    {
        y.TheCallingAssembly();
        y.WithDefaultConventions();
    });

    x.For<Lazy<IFoo>>().Use(y => new Lazy<IFoo>(y.GetInstance<Foo>));
    x.For<Lazy<IBar>>().Use(y => new Lazy<IBar>(y.GetInstance<Bar>));
    x.For<Lazy<IBaz>>().Use(y => new Lazy<IBaz>(y.GetInstance<Baz>));
});

如果这是自动完成的话会更好。理想情况下,以下语法会很好。

x.For(typeof(Lazy<>)).Use(typeof(Lazy<>));

不幸的是,在运行时,StructureMap将尝试为Lazy<T>找到“最贪婪”的构造函数并在public Lazy(Func<T> valueFactory, bool isThreadSafe)上结算。因为它不知道如何处理boolean isThreadSafe参数。它会引发异常。您可以显式告诉 StructureMap使用什么值。

x.For(typeof(Lazy<>)).Use(typeof(Lazy<>))
 .CtorDependency<bool>("isThreadSafe").Is(true);

将停止异常,并对isThreadSafe参数使用“true”的值。 Lazy的文档声明默认Lazy(Func<T> valueFactory)构造函数的线程安全模式是LazyThreadSafetyMode.ExecutionAndPublication,这也是通过将true传递给上面构造函数的isThreadSafe参数得到的,所以我们将得到相同的行为就好像我们首先调用了我们实际想要使用的构造函数(例如Lazy(Func<T> valueFactory))。您可以更详细地了解Lazy类here

我意识到这并没有直接回答你关于自定义扫描仪课程的问题,但它应该给你一个良好的开端,我希望。