在这种情况下我可以避免反思吗?

时间:2012-06-26 10:22:35

标签: c#

假设我有这些类层次结构:

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对象,并在进程结束时调用Update。我确定将实现Update方法,所以我写了这段代码:

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 个答案:

答案 0 :(得分:5)

如果不触及这些类,您可以做的一件事就是创建自己的接口IUpdateable,然后创建一个新的并行层次结构,如

interface IUpdateable
{
    void Update();
}

public class A : Original.A, IUpdateable {}

如果您可以使用自己的叶类而不是原始叶类,则可以将该方法编写为接受IUpdateable参数。但是,虽然使用自己的类并不是很困难(using alias directives可以提供帮助),生成它们并不那么容易(您需要在每次调用之后插入自定义代码)创建原始类的任何实例的原始库,如果该实例的类型为Parent,则返回原点。)

不要忘记即时迫害原始代码的作者。

答案 1 :(得分: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();
    }
}

答案 2 :(得分: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;
        }
    }
}

答案 3 :(得分:0)

创建一个名为UpdatableParent的临时类,它包含一个Update()方法,并从中派生所有其他类。然后使用UpdateableParent作为DoSomething()参数的类型。