役に立ちましたか?

解決

編集: なお、この回答される前の質問は完全に変化し、編集できるようになります。そのため、今となっただけの問題としてのものを記載しています。ご勘弁をすべての"ぶポインタ".:-)


答え:

のコードだけを掲載していな代替鋳造 IFoo<T>.ない場合は、コンパイラにおいて警告(マに、少なくとも).

詳しい答え:

あなたのコードが実際に可能です。具体的には、必要なものはキャスト問題となるのでしょうか。

いかにお電話ファクトリメソッドより以下のようになります:

var stringFoo = FooFactory.CreateFoo<string>();

きのテンプレートパラメータstring この場合は明示的にでから派生できない方法で引数(この場合がありません実際には、であります。当然のことながら、ファクトリメソッドを返却する IFoo<string>.

いて明示的に指定の型での実行時間を過ごすことだけでも書き:

var stringFoo = StringFoo.Create();

その場合は、ファクトリメソッド内 StringFoo, このように、無条件では、あなた:

public class StringFoo : IFoo<string>
{
    ...

    public static StringFoo Create()  // or alternatively, return an IFoo<string>
    {
        return new StringFoo();
    }
}

これによりパターン他 IFoo<T> 実装においても、また、 if チェーンまたは switch ブロック内 FooFactory.CreateFoo<T>, としてコードを軽くする必要性キャスト(ご関係にあります。

なく間違っているのは、私が認識したファクトリメソッドの支援以上のオブジェクトタイプ 有用な場合もあ;うですがお客様の原因となり困ります。


P.S.: を感じるかもしれませんが一つ一IoC容器に興味深い。彼らは常に設定されていること、こうした取り組みは、ご登録コンクリートの種類(実装クラス)要旨ーマンインタフェース、例えばこちらを使用 Autofac):

var builder = new ContainerBuilder();
builder.RegisterType<StringFoo>().As<IFoo<string>>();

その後、請求することができオブジェクトのインスタンスの抽象タイプ:

using (var container = builder.Build())
{
    var stringFoo = container.Resolve<IFoo<string>>();
    ...
}

Resolve 方法は、面白いことでした。ご提供する抽象タイプを使用して、登録の種類を返しますコンクリート型のオブジェクト StringFoo.うかっていることを確認してください音を覚えます。:-)

他のヒント

あなたは、このメカニズムで解決されている問題を記述することはできますか?それに近づくための明確な方法は、最も可能性があります。

編集

そして、はい、コードの臭いです。あなたが戻って、単一の型にそれを制約し、実行時例外を発生させる以外あなたは、任意のタイプのためのオープン左の部屋を持っています。なぜ、そのような場合には型パラメータがありますか?

あなたはこのような何かを試みることができる...

public static class FooFactory
{
    private static readonly Dictionary<Type, Type> FooTypesLookup;

    static FooFactory()
    {
        FooTypesLookup = (from type in typeof(FooFactory).Assembly.GetExportedTypes()
                          let fooInterface =
                            type.GetInterfaces().FirstOrDefault(
                                x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IFoo<>))
                          where fooInterface != null
                          let firstTypeArgument = fooInterface.GetGenericArguments().First()
                          select new { Type = type, TypeArgument = firstTypeArgument })
            .ToDictionary(x => x.TypeArgument, x => x.Type);
    }

    public static IFoo<T> CreateFoo<T>()
    {
        var genericArgumentType = typeof(T);
        Type closedFooType;
        return FooTypesLookup.TryGetValue(genericArgumentType, out closedFooType)
                ? (IFoo<T>) Activator.CreateInstance(closedFooType)
                : null;
    }
}

いっそ、あなたの好みのIoCコンテナ(ウィンザー、構造マップなど)を導入し、そこにIFooを実装するすべてのタイプを登録して、Activator.CreateInstanceコールの代わりに、必要なときにそれらを解決します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top