2

これらのクラス階層があるとしましょう:

public abstract class Parent {
}

public class A : Parent {
    public void Update() { }
}

public class B : Parent {
    public void Update() { }
}

public class C : Parent {
    public void Update() { }
    public void Update(bool force) { }

}

ご覧のとおり、 のすべての子孫にParentは、パラメーターのない Update メソッドがあります。

あらゆる種類のオブジェクトで動作し、プロセスの最後にParent呼び出すことができるユーティリティ クラスを作成したいと考えています。UpdateUpdate メソッドが実装されると確信しているので、次のコードを書きました。

public class ParentUtilities {
    private static readonly Dictionary<Type, MethodInfo> g_UpdateMethods = new Dictionary<Type, MethodInfo>{
        { typeof(A), typeof(A).GetMethod("Update", new Type[] {})},
        { typeof(B), typeof(B).GetMethod("Update", new Type[] {})},
        { typeof(C), typeof(C).GetMethod("Update", new Type[] {})}
    };

    public static void DoSomething(Parent p)
    {
          CalculateTheMeaningOfTheLife(p);             

          g_UpdateMethods[p.GetType()].Invoke(p, null);
    }
}

クラス階層を制御できないため(サードパーティのアセンブリからのものです) 。ユーティリティ クラスのみを変更できます。どうすればそのような微調整を避けることができますか?

私は.Net 3.5 SP1に固執しているので、動的を使用できません。

4

4 に答える 4

5

これらのクラスに触れずにできることの 1 つは、独自のインターフェイスを作成してからIUpdateable、次のように独自の新しい並列階層を作成することです。

interface IUpdateable
{
    void Update();
}

public class A : Original.A, IUpdateable {}

元のリーフ クラスの代わりに独自のリーフ クラスを使用できる場合は、IUpdateableパラメーターを受け入れるメソッドを記述できます。ただし、独自のクラスを使用することはそれほど難しくありませんが (using エイリアス ディレクティブが役立ちます)、それらを生成することはそれほど簡単ではありません (元のクラスのインスタンスを作成する元のライブラリを呼び出すたびにカスタム コードを挿入する必要があり、そのインスタンスが振り出しに戻るときに入力しParentます)。

元のコードの作成者を見つけ次第迫害することも忘れないでください。

于 2012-06-26T10:26:35.833 に答える
2

適切に定義されたインターフェイス実装を使用して、ラッパー クラスを作成できます。

使用法

class Program
{
    static void Main(string[] args)
    {
        A a = new A();
        IUpdatable wrapper = new AWrapper(a);
        wrapper.Update(); // prints A.Update
    }
}

ラッパー クラスとインターフェイス

interface IUpdatable
{
    void Update();
}


public abstract class Parent { }

public class A : Parent
{
    public void Update()
    {
        Console.WriteLine("A.Update");
    }
}

public class AWrapper : IUpdatable
{
    public A Inner { get; private set; }
    public AWrapper(A a)
    {
        Inner = a;
    }

    public void Update()
    {
        Inner.Update();
    }
}
于 2012-06-26T10:42:53.337 に答える
1

既知の(非常に)小さな子クラスのセットがある場合は、次のようにすることができます。

public class ParentUtilities
{
    public static void DoSomething(Parent p)
    {
        CalculateTheMeaningOfTheLife(p);

        var a = p as A;
        if (a != null)
        {
            a.Update();
            return;
        }

        var b = p as B;
        if (b != null)
        {
            b.Update();
            return;
        }

        var c = p as C;
        if (c != null)
        {
            c.Update();
            return;
        }
    }
}
于 2012-06-26T10:27:54.757 に答える
0

Update() メソッドを含む UpdatableParent という暫定クラスを作成し、そこから他のすべてのクラスを派生させます。次に、DoSomething() 引数の型として UpdateableParent を使用します。

于 2012-06-26T10:27:56.170 に答える