2

以下の「MethodA」を定義する方法を探しています。これにより、クラス定義(System.Type)が返され、そのタイプのインスタンスが「InterfaceB」を実装します。

interface IMyInterface
{
  TType MethodA<TType, TInterface>() 
    : where TType : System.Type
    : where [instanceOf(TType)] : TInterface
}

(注:もちろん、instanceOfは本物ではありません...)

コンパイル時にこの種の検証を取得することは不可能だと思います。誰かが私を間違っていると証明してくれることを願っています。

ご指導ありがとうございます。

編集:返されるものがSystem.Typeであり、この後のコードが実行できることをより具体的にすることを期待して、これを更新しました:

var classType = myInterface.MethodA<(something, ISomeInterface)>();
ISomeInterface = new classType();  //--Assuming default constructor

私はまだこの部分に焦点を当てていませんが、私の主要な質問の理論的構成についてもっと興味があります。

4

2 に答える 2

3

あなたの質問には2つの解釈があります。1つは些細なことで、もう1つは不可能なので、先に進んで両方をカバーします。

  1. System.Typeとの両方を実装する型のインスタンスを返したいとしますTInterface

    これは些細なことです。とを使用するだけwhere TType : Typeですwhere TType : TInterface

  2. System.Typeから継承する型を表すインスタンスを返したいとしますTInterface

    これは、.NET(およびC#)型システムで指定することはできません。

    型システムは、型階層自体からの情報のみを解決できますが、制限された実行時プロパティ値のような「コントラクト」を強制することはできません。デフォルトコンストラクターなどに関していくつかのハックがありますが、私が知る限り、既存のメソッドをテストすることさえできません(たとえば、Qi etal。は言うまでもなくC++テンプレートとは異なります)。

アップデート

MichaelGraczykからのコメントを確認してください。

また、.NET用のコードコントラクトチェッカー(静的およびランタイム)があることを知りました:Microsoft DevLabs Code-Contractsfor.NET。私はそれらを使ったことがなく、それらについても新しいものではありませんが、それは面白そうです!

ただ、見なくても過負荷解決などでは使えないと思います。

于 2012-07-25T22:30:40.543 に答える
0

この状況では:

// We have an interface...
interface InterfaceB {}

// And this class implements the interface.
class ImplementsB : InterfaceB {}

// But this class does not.
class DoesNotImplementB {}

次のように定義できますMethodA

static Type MethodA<TClass, TInterface>()
    where TClass : TInterface
{
    return typeof(TClass);
}

次に、以下が機能します。

Type t = MethodA<ImplementsB, InterfaceB>();

ただし、これによりコンパイル時エラーが発生します。

Type t = MethodA<DoesNotImplementB, InterfaceB>();

タイプ'DoesNotImplementB'は、ジェネリック型またはメソッド'MethodA <TClass、TInterface>()'のタイプパラメーター'TClass'として使用できません。'DoesNotImplementB'から'InterfaceB'への暗黙の参照変換はありません。

したがって、このようにして、の結果がを実装するクラスの結果でMethodAあることが確実になります。そのオブジェクトが与えられると、後で次のようにインスタンス化できます。TypeTInterfaceType

public object Instantiate(Type type)
{
    // Call the default constructor.
    // You can change this to call any constructor you want.
    var constructor = type.GetConstructor(Type.EmptyTypes);
    var instance = constructor.Invoke(new object[0]);
    return instance;
}

Typeが何らかのインターフェイスと互換性があることがわかっている場合はTInterface、次のような追加のメソッドを使用してキャストを回避できます。

public TInterface Instantiate<TInterface>(Type type)
{
    return (TInterface)Instantiate(type);
}

ただし、が何らかの形で実装されていない場合typeは、実行時に取得します。コンパイル時に特定のインターフェイスを実装する型になるように制約する方法はありません。ただし、実行時に、例外を回避するためにチェックすることができます。TypeTInterfaceInvalidCastExceptionTypeInvalidCastException

public TInterface Instantiate<TInterface>(Type type)
{
    if (!typeof(TInterface).IsAssignableFrom(type))
        throw new Exception("Wrong type!");
    return (TInterface)Instantiate(type);
}

typeof(TType)これはオブジェクトを生成する式であることに注意してください。そのTypeため、どこにtypeof()いてもそれを任意の変数に置き換えることができType、その逆も可能です。

これはあなたが知りたかったことですか?

于 2012-07-26T00:08:32.853 に答える