3

渡されたジェネリック型のみに基づいて BuildIt 関数が具象型を返すファクトリ型コードを試しています。ジェネリック型は BaseAbstract クラスの子孫に制限されています。

Buildit 関数には、ジェネリック型と、params のリストが必要です (params は、具象クラスを作成するときに BuildIt 関数のコンストラクター パラメーターとして使用されます)。

以下のコード例は期待どおりに動作します ("A" の後に "B" が表示されます)。

しかし、次のようなものを呼び出そうとすると問題が発生します。

        var b = fs.BuildIt<B>("B", "C");

B クラスには 2 つのパラメーターを持つコンストラクターがないため、これは実行時に失敗します。

コンパイル時にこれが失敗することを除いて、このようなことをすることは可能ですか? そうでない場合、コンパイル時のチェックを可能にする別の方法はありますか (これをすべて破棄して、まったく別のものを開始する必要があるかどうかは問題ではありません)。

サンプルコード

public abstract class BaseAbstract
{
    public string Name ="";
    public override string ToString ()
    {
        return Name;
    }
}

public class A : BaseAbstract
{
    public A()
    {
        Name = "A";
    }
}

public class B : BaseAbstract
{
    public B()
    {
    }

    public B(string param)
    {
        Name = param;
    }
}

public class Factory
{
    public T BuildIt<T>(params object[] args) where T : BaseAbstract, new()
    {
        T x = (T)Activator.CreateInstance(typeof(T), args);
        return x;
    }
}

public class MainClass
{
    public static void Main (string[] args)
    {
        //These are fine
        Factory fs = new Factory();
        var a = fs.BuildIt<A>();
        var b = fs.BuildIt<B>("B");
        Console.WriteLine (a);
        Console.WriteLine (b);

          //This would cause runtime error because of the "C" paramter
          //var b2 = fs.BuildIt<B>("B", "C");

    }
}
4

1 に答える 1

2

ランタイムテクノロジーであるリフレクションを使用しているため、そうではありません...インスタンスを作成できないことをコンパイラが認識する唯一の方法は、コードを実行することです...少なくともCAASが表示されるまで。

メソッドのジェネリック型に new() 制約を強制し (すべての型にパラメーターなしのコンストラクターがあることを確認します)、コンストラクターのパラメーターを型の代わりにプロパティとしてマップしますか? 不変性が必要な場合は理想的ではないかもしれませんが、リフレクションはとにかくプライベートタイプなどに書き込むことができます...

これは、 ArgumentExceptionクラスが作成されたシナリオのほとんどの種類です...何かが期待どおりに機能しない場合はスローします。

于 2013-06-20T04:48:57.623 に答える