2

ジェネリック型パラメーターを持つ次のクラスがあります。

public class ContentService<T> : IContentService where T : DataString, new()
{       
    public ContentService(IEnvironment environment, 
                          ILogger logger)
    {
        _environment = environment;
        _logger = logger;
    }
...
}

DataString は抽象クラスであり、アプリケーションが ContentService のインスタンスを作成するたびに、Structure Map が具体的な実装 (XmlDataString) を使用するようにします。これを行うと、構造マップはすでに IEnvironment と ILogger の具体的な実装を注入しています。

バージョン 1:

_contentService = ObjectFactory.GetInstance<ContentService<DataString>>();

...しかし、ステップスルーすると、XmlDataString ではなく、DataString の型パラメーターを使用して ContentService が作成されます。デフォルトのインスタンスを設定する web.config に次の 3 つのエントリがあります。

  • IEnvironment -> TestEnvironment
  • ILogger -> Log4NetLogger
  • データ文字列 -> XmlDataString

構造マップのサイトには、ジェネリックについてこう書かれていますが、その例を実際の問題に関連付けることはできないようです。

このアプローチは機能しますが、コンストラクターの引数の自動配線が失われており、非常に見苦しく見えます: バージョン 2:

Type typeOfDataString = ObjectFactory.GetInstance<DataString>().GetType();
Type genericClass = typeof(ContentService<>);
Type constructedClass = genericClass.MakeGenericType(typeOfDataString);
_contentService = (IContentService)Activator.CreateInstance(constructedClass, 
            ObjectFactory.GetInstance<IEnvironment>(), 
            ObjectFactory.GetInstance<ILogger>());

最初のバージョンで何が間違っているか、または 2 番目のバージョンをどのように改善できるか教えてもらえますか?

4

1 に答える 1

1

まず、 を書くObjectFactory.GetInstance<ContentService<DataString>>()と元に戻せませんContentService<XmlDataString>。これは別の互換性のない型だからです。

しかし、実際には が必要なようIContentServiceですObjectFactory.GetInstance<IContentService>()。これにより、登録した の実装が返されるIContentServiceので、これを行う必要があります: register ContentService<XmlDataString>for IContentService. あなたがXmlDataString登録したという事実DataStringは、これとは何の関係もありません。

web.config でジェネリック型を表すのに問題がある場合はContentService<XmlDataString>、(C# ではなく) ジェネリック型の .Net 表現を使用するとうまくいくと思います。ContentService`1[[XmlDataString]]あなたの場合、それはおそらく名前空間とおそらくアセンブリも追加された のようなものになります。

于 2012-04-04T17:09:06.823 に答える