1

我想注册所有实现的类型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 配置它?

4

1 回答 1

3

更新: 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<>));

Lazy<T>不幸的是,在运行时,StructureMap 将尝试为public Lazy(Func<T> valueFactory, bool isThreadSafe). 因为它不知道如何处理布尔 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 类。

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

于 2011-07-29T16:59:06.870 回答