4

私は次のものを持っています:

public interface IConverter<TValue, TConverted>
{     
}

public interface IConverterProvider
{
    IConverter<TValue, TConverted> GetConverter<TValue, TConverted>();
}

セットアップ時のバインディングの例:

Bind<IConverter<System.Int32, System.String>>().To<Int32ToStringConverter>();
Bind<IConverter<System.Guid, System.String>>().To<GuidToStringConverter>();

したがって、固定コンバーターのコレクションがあり、重複するバインディングはありません。

[質問] 私の質問は、IConverterProvider を実装し、シングルトンにマップされた利用可能なバインディングの辞書を挿入するにはどうすればよいですか? つまり、実行時のサービス ロケーター パターンを回避する方法です。

現在、毎回 NInject カーネルを使用して解決していますが、これはアンチパターンだと思います。私が欲しいのは次のようなものです:

public class ConverterProvider : IConverterProvider
{
    private Dictionary<Type, object> _converters;

    public ConverterProvider(Dictionary<Type, object> converters)
    {
        _converters = converters;
    }

    public IConverter<TValue, TConverted> GetConverter<TValue, TConverted>()
    {
        var fullTypeResolve = typeof (IConverter<,>).MakeGenericType(typeof (TValue), typeof (TConverted));

        return _converters.Where(x => x.Key == fullTypeResolve).Select(x=>x.Value).Cast<IConverter<TValue, TConverted>>().Single();
    }
}

しかし、これには事実上、依存性注入カーネルからすべての IConverter<,> のリストを解決して取得できる必要があり、NInject からこれを行う以前の試みは成功していません。

4

2 に答える 2

1

これはによってサポートされていますNinject.Extensions.Factory

Bind<IConverter<System.Int32, System.String>>().To<Int32ToStringConverter>();
Bind<IConverter<System.Guid, System.String>>().To<GuidToStringConverter>();
Bind<IConverterProvider>().ToFactory();

実装は必要ありません

名前をGetで始まらない別の名前に変更GetConverterするCreateConverter

于 2013-02-28T21:53:46.240 に答える
0

私は通常、次のようなファクトリー(またはここにあるプロバイダー)を作成します。

public class ConverterFactory : IConverterFactory
{
    private readonly IResolutionRoot resolutionRoot;

    public ConverterFactory(IResolutionRoot resolutionRoot)
    {
        this.resolutionRoot = resolutionRoot;
    }

    public IConverter<TValue, TConverted> CreateConverter()
    {
        Type converterType = typeof(IConverter<,>).MakeGenericType(typeof(TValue), typeof(TConverted));
        return this.resolutionRoot.Get(converterType);
    }
}

実行時に Ninject を使用して何かを作成することは想定されていませんが、実際には避けられない場合があります。シングルトンの動作を取得するにはInSingletonScope()、通常どおりに定義するだけです。

型がジェネリックでない場合は、実行時に選択する代わりに、インターフェイスのすべての実装を注入できIResolutionRootます。次のようなパーサー ファクトリがあります。

public class ParserFactory : IParserFactory
{
    private readonly IEnumerable<IParser> parsers;

    public ParserFactory(IEnumerable<IParser> parsers)
    {
        this.parsers = parsers;
    }

    public IParser CreateParser(string someInput)
    {
        foreach (var parser in this.parsers)
        {
            if (parser.CanParse(someInput))
            {
                return parser;
            }
        }
    }
}

Ninject は、インターフェイスのすべての具体的な実装を含む を自動的に注入するIEnumerableため、新しい実装を追加することは、マッピングを追加するのと同じくらい簡単です。とは言えないので、ジェネリック型でそれを行う方法がわかりませんIEnumerable<IConverter<,>>

于 2013-02-27T20:35:19.523 に答える