3

私のアプリケーションには、入力と出力を使用して相互にリンクされているコンポーネントがあります。交換されるデータはどのタイプでもかまいませんので、ジェネリックを使用します。

public interface IInputVariable<T>
{
    IOutputVariable<T> Source { get; set; }
}


public interface IOutputVariable<T>
{
    T Value { get; set; }
}

別のクラスでは、コンポーネントは互いにリンクされています。リンクされているコンポーネントは、ファイルから派生しています。リンクを行うクラスは、どのタイプの入出力交換を行うかについての知識を持っていません。このクラスは、次のコードでそれらを接続するだけです。

IOutputVariable<double> output;
Type argumentType = output.GetType().GetGenericArguments()[0];
IInputVariable<argumentType> input = new BasicInputVariable<argumentType>();
input.Source = output;

このコードは、argumentTypeをジェネリック引数として使用できないため、コンパイルされません。これを定式化する正しい方法はありますか?または、引数の型を知らなくてもジェネリック変数を宣言することは可能ですか?

4

2 に答える 2

2

プロパティを設定する最も簡単な方法は、コンストラクターをSource作成することです。BasicInputVariable<T>IOutputVariable<T>

public BasicInputVariable(IOutputVariable<T> source)
{
    Source = source;
}

次に、簡単にインスタンス化できます。

IOutputVariable<double> output;
Type argumentType = output.GetType().GetGenericArguments()[0];
object input = Activator.CreateInstance(typeof(BasicInputVariable<>)
                                       .MakeGenericType(argumentType), output);

もう 1 つの方法は、Sourceプロパティを提供できるインターフェイスを作成して実装することです。

public interface ISetSource
{
    object Source { get; set; }
}

public class BasicInputVariable<T> : IInputVariable<T>, ISetSource
{
    public IOutputVariable<T> Source { get; set; }

    object ISetSource.Source
    {
        get { return Source; }
        set { Source = (IOutputVariable<T>) value; }
    }
}

これで、プロパティにアクセスできSourceます:

IOutputVariable<double> output;
var input = (ISetSource) Activator.CreateInstance(typeof (BasicInputVariable<>)
                                                 .MakeGenericType(argumentType));
input.Source = output;

in/out ジェネリック パラメータを使用すると、よりタイプ セーフになる可能性がありますが、残念ながら、値型では使用できません...

于 2012-12-23T18:54:08.077 に答える
0

注意:これは本当に醜いハックです。お勧めしません..

.NET 4.0 を使用している場合:

IOutputVariable<double> output = something;
dynamic input = Activator
                .CreateInstance(typeof(BasicInputVariable<>)
                                .MakeGenericType(output
                                                 .GetType()
                                                 .GetGenericArguments()[0]));
//or may be:
//dynamic input = typeof(BasicInputVariable<>)
//                .MakeGenericType(output
//                                 .GetType()
//                                 .GetGenericArguments()[0])
//                .GetConstructor(new Type[0])
//                .Invoke(new object[0]);

input.Source = output;

しかし、型引数自体をコンストラクターdoubleに直接渡すことを妨げている理由がわかりませんか?BasicInputVariable

IOutputVariable<double> output = something;
IInputVariable<double> input = new BasicInputVariable<double>();
input.Source = output;

型引数が何でもよい場合、メソッド全体をジェネリックにしてみませんか? 多分:

void Method<T>()
{
    IOutputVariable<T> output = something;
    IInputVariable<T> input = new BasicInputVariable<T>();
    input.Source = output;
}

T入力変数と出力変数の両方が同じであるため、これは機能します。


詳細を知らずに、より良い解決策を考えるのは難しいですが、真剣に、最初に設計を再考する必要があります。

于 2012-12-23T18:19:47.357 に答える