假设我有这些类层次结构:
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,我无法使用动态。
答案 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()参数的类型。