1

ジェネリッククラスIManagerの型として使用できるように、実装しているすべての型を登録したいと考えています。TLazy<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<>));

残念ながら、実行時に StructureMap は の「最も貪欲な」コンストラクターを見つけてLazy<T>解決しようとします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されています。これは、上記のコンストラクターの isThreadSafe パラメーターに true を渡すことによって得られるものでもあるため、実際にコンストラクターを呼び出した場合と同じ動作が得られます。そもそも使いたかった(例Lazy(Func<T> valueFactory))。Lazy クラスの詳細については、こちらを参照してください。

これがカスタム スキャナー クラスに関するあなたの質問に直接答えているわけではないことは承知していますが、良いスタートが切れるはずです。

于 2011-07-29T16:59:06.870 に答える