3

DoSomething()メソッドが呼び出される基になるインターフェイスを特定するにはどうすればよいですか? 追加の質問: MyClass コンストラクターの基になるインターフェイスを既に決定できますか? インスタンス化時にわからないので、そうではないと思いますよね?

編集:明示的なインターフェイスの実装を探しているのではなく、基になるインターフェイスを決定する別の方法を探しています。

public interface ITest
{
    void DoSomething();
    //....more methods
}

public interface IDecoy
{
    void DoSomething();
    //...more methods
}

public class MyClass : ITest, IDecoy
{
    public void DoSomething()
    {
        //Question: How can I determine the underlying interface that called this method?
        //at one time it is ITest, at another IDecoy. How can I figure out which one at each time?
    }
}

public class Test
{
    public Test()
    {
        ITest myClassInstance1 = new MyClass();
        IDecoy myClassInstance2 = new MyClass();

        myClassInstance1.DoSomething();
        myClassInstance2.DoSomething();
    }
}
4

2 に答える 2

6
public class MyClass : ITest, IDecoy
{
    void ITest.DoSomething()
    {
        //called with ITest 
    }
    void IDecoy.DoSomething()
    {
        //called with IDecoy 
    }
}
于 2013-08-13T07:51:45.093 に答える
2

この質問は非常に興味深いので、解決策が提示されていなくても、どのインターフェースが使用されているかを特定する方法を見つけることができるかどうかを調べてみました。

私が使用しているソリューションは、基本的に、呼び出し元の IL コードで呼び出されたメソッドのメタデータ トークンを検索し、これDoSomethingを各インターフェイスからのメソッドのメタデータ トークンと照合します。

public void DoSomething()
{
    StackFrame CallerFrame;
    StackTrace CallStack;
    int CodeOffset;
    MethodBody MethodBody;
    int MethodToken;
    int TokenIDecoy;
    int TokenITest;

    // Get the metadata tokens for both interface methods
    TokenIDecoy = Type.GetType("Proto.SO18203446.IDecoy").GetMethod("DoSomething").MetadataToken;
    TokenITest = Type.GetType("Proto.SO18203446.ITest").GetMethod("DoSomething").MetadataToken;

    // Get the caller
    CallStack = new StackTrace();
    CallerFrame = CallStack.GetFrame(1);

    // Get the metadata token called by the IL
    CodeOffset = CallerFrame.GetILOffset();
    MethodBody = CallerFrame.GetMethod().GetMethodBody();
    MethodToken = BitConverter.ToInt32(MethodBody.GetILAsByteArray(), CodeOffset - 4);

    // Check to see which interface was used
    if (MethodToken == TokenIDecoy)
        Console.WriteLine("IDecoy was called");
    else if (MethodToken == TokenITest)
        Console.WriteLine("ITest was called");
    else
        Console.WriteLine("Not sure what happened here");
}

GetTypecall パラメーターを自分の名前空間に変更することを忘れないでください (私の名前Proto.SO18203446はそうですが、あなたの名前は別のものである可能性が非常に高いです)。

プロセスの手順は簡単です。

  • DoSomething各インターフェイスメソッドのメタデータ トークンを検索する
  • 呼び出しフレーム ( を呼び出すフレーム) を見つけますDoSomething
  • メソッドへの呼び出しの IL オフセットを検索し、DoSomethingそのメタデータ トークンを抽出します。
  • 呼び出されたメタデータ トークンをDoSomethingインターフェイスのそれぞれのトークンと比較します

私はこのコードを推奨または承認していないことを付け加えたいと思います - それは学術的な観点からあなたの目的を達成することが可能であることを証明することです.

于 2013-08-13T10:24:29.063 に答える