6

次の方法でクラスを設定しています。

public abstract FooClass {
    public FooClass() {
        // init stuff;
    }

    public void RandomMethod() {
        // do stuff;
    }

    public abstract WhatIWantToShim();
}

私がやりたいことは、次のように ShimFooClass に WhatIWantToShim を設定することです。

ShimFooClass.AllInstances.WhatIWantToShim = () => Boo();

RandomMethod を問題なく設定できます。

ShimFooClass.AllInstances.RandomMethod = () => CalculatePi();

ただし、生成された ShimFooClass は、ShimFooClass の AllInstances プロパティに WhatIWantToShim プロパティを作成しないようです。

http://msdn.microsoft.com/en-us/library/hh549176.aspx#bkmk_shim_basicsを見ましたが、抽象メソッドについては何も表示されません。サポートされていない参照されている唯一のものは、ファイナライザーです。ここで何が起こっているのか、このシナリオがサポートされているかどうか知っている人はいますか?

4

2 に答える 2

1

他の回答が質問に答えなかったと確信しているため、ここで返信しています。今後の検索で有用な情報が返されるようにします。

まず、インターフェイスをシムすることはできません。抽象メソッドはインターフェイスに相当します。さらに、理由はありません。

{
    bool wasAbstractMethodCalled = false;
    var targetStub = new StubFooClass()
    {
        WhatIWantToShim01 = () => wasAbstractMethodCalled = true
    };
    ShimFooClass.AllInstances.RandomMethod = @class => targetStub.CalculatePi();
    targetStub.WhatIWantToShim();
    Assert.IsTrue(wasAbstractMethodCalled, "The WhatIWantToShim method was not called.");
}

上記は以前の回答の簡略版であり、割り当てたばかりのアクションを呼び出すだけです。これはおそらくあなたの意図ではありません。

あなたがシムする理由を覚えておいてください。テストしているメソッド内でのメソッド呼び出しの影響を回避したい場合は、シムを使用します。抽象メソッドには本体がないため、何にも影響を与えることができません。これが役立つのは、シムが最初に利用できる子クラスだけです。

問題が発生する可能性がある唯一の状況は、3 番目のクラスが密かに抽象クラスのインスタンスを保持し、それを子クラスでインスタンス化する場合です。それを偽造することはできません。しかし、これはひどい設計です。インスタンスは何らかのメソッドから取得する必要があります (これは shim できます)、または渡される必要があります (DI は良いことだからです!)。抽象化をまったく使用していません。

于 2013-10-08T22:28:17.233 に答える