web-dev-qa-db-ja.com

インターフェイスインスタンスの背後にある具象型を見つける

簡単に言うと、Objectインスタンスとして渡される特定のTypeでタスクを実行するC#関数があります。クラスインスタンスが渡されると、すべて正常に機能します。ただし、オブジェクトがインターフェイスとして宣言されている場合、具体的なクラスを見つけて、そのクラスタイプに対してアクションを実行したいと思います。

これは、至る所に存在する悪い例です(不正なプロパティの大文字小文字の区別など):

public interface IA
{
    int a { get; set; }
}
public class B : IA
{
    public int a { get; set; }
    public int b { get; set; }
}
public class C : IA
{
    public int a { get; set; }
    public int c { get; set; }
}

// snip

IA myBObject = new B();
PerformAction(myBObject);

IA myCObject = new C();
PerformAction(myCObject);

// snip

void PerformAction(object myObject)
{
    Type objectType = myObject.GetType();   // Here is where I get typeof(IA)
    if ( objectType.IsInterface )
    {
        // I want to determine the actual Concrete Type, i.e. either B or C
        // objectType = DetermineConcreteType(objectType);
    }
    // snip - other actions on objectType
}

PerformActionのコードでReflectionをパラメーターに対して使用し、IAのインスタンスだけでなく、Bのインスタンスであり、GetProperties()を介してプロパティ "b"を表示することを確認します。 .GetType()を使用する場合、IAのタイプを取得します-必要なものではありません。

PerformActionは、IAのインスタンスの基になる具象型をどのように決定できますか?

Abstractクラスを使用することを提案したい人もいるかもしれませんが、それは私の悪い例の制限にすぎません。変数は元々、インターフェイスインスタンスとして宣言されます。

43
Rowan
Type objectType = myObject.GetType();

あなたの例によると、まだ具体的なタイプを与える必要があります。

75
Stan R.

あなたがしているのは本当にベッドのデザインですが、あなたはこのようにそれをチェックすることができます反射を使用する必要はありません

void PerformAction(object myObject)
{
    B objectType = myObject as B;   // Here is where I get typeof(IA)
    if ( objectType != null )
    {
        //use objectType.b
    }
    else
    {
       //Same with A 
    }
    // snip - other actions on objectType
}
5
Arsen Mkrtchyan

悪いデザインについては同意しなければなりません。インターフェイスがある場合、具体的な実装を気にせずにいくつかの一般的な機能を利用する必要があるためです。あなたが例だとすると、PerformActionメソッドは実際にインターフェースの一部であるように思えます:

public interface IA
{
    int a { get; set; }
    void PerformAction();
}

public class B: IA
{
    public int a { get; set; }
    public int b { get; set; }

    public void PerformAction()
    {
        // perform action specific to B
    }
}

public class C : IA
{
    public int a { get; set; }
    public int c { get; set; }

    public void PerformAction()
    {
        // perform action specific to C
    }
}

void PerformActionOn(IA instance)
{
    if (instance == null) throw new ArgumentNullException("instance");

    instance.PerformAction();

    // Do some other common work...
}


B b = new B();
C c = new C();

PerformActionOn(b);
PerformActionOn(c);
5
jrista

インターフェイスのインスタンスを持つことはできません。したがって、インターフェイスまたは具象型のどちらを扱うのかを判断することはできません。常に具象型を扱うからです。ですから、あなたの質問が意味をなすかどうかはわかりません。正確に何をしようとしているのですか?

3
Chris Johnston

多分あなたは is演算子 を探しています

void PerformAction(object myObject)
{
    if (myObject is B)
    {
        B myBObject = myObject as B;
        myBObject.b = 1;
    }

    if (myObject is C)
    {
        C myCObject = myObject as C;
        myCObject.c = 1;
    }

    // snip - other actions on objectType
}
1
kova