我有3个班级:**父**,** Child1 **和** Child2 **。 Child1&子2扩展父,他们**不能**修改。
有一个类Action定义如下:
public class Action {
public static void perform(Parent p) {
if (p instanceof Child1) {
action((Child1)p);
}
else if (p instanceof Child2) {
action((Child2)p);
}
else {
action(p);
}
}
private static void action(Parent p) {
...
}
private static void action(Child1 c1) {
...
}
private static void action(Child2 c2) {
...
}
}
Parent p = new Child1();
Action.perform(p);
如果没有 instanceof 运算符,有没有办法获得与上面相同的行为?
======
(修改)
PS:Action.perform的给定参数类型是Parent,但它的值是Child1,所以我认为方法重载不起作用....
答案 0 :(得分:0)
不幸的是,我认为你不得不求助于反思来解决这个问题。
答案 1 :(得分:0)
这里有两个C#解决方案,一个基本上是相同但更整洁,并且当你有少量子类时很好。
public class Parent
{
}
public class Child1 : Parent
{
}
public class Child2 : Parent
{
}
public class Action
{
private static Dictionary<Type, Action<Parent>> _d = new Dictionary<Type, Action<Parent>>()
{
{typeof(Child1), p=>action((Child1)p)},
{typeof(Child2), p=>action((Child2)p)},
{typeof(Parent), p=>action(p)}
};
public static void perform(Parent p)
{
_d[p.GetType()](p);
}
private static void action(Parent p)
{
}
private static void action(Child1 c1)
{
}
private static void action(Child2 c2)
{
}
}
class Program
{
static void Main(string[] args)
{
Parent p = new Child1();
Action.perform(p);
}
}`enter code here`
无论如何它打破了OCP但比使用反射更快。这个不破坏OCP但使用反射来填充字典:
public class Action
{
private static Dictionary<Type, Action<Parent>> _d;
static Action()
{
Initialize();
}
private static void Initialize()
{
var methods = typeof(Action)
.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
.Where(IsActionMethod)
.ToList();
_d = methods.ToDictionary(m => m.GetParameters().First().ParameterType,
m => (Action<Parent>) (x => m.Invoke(null, new[] {x})));
}
private static bool IsActionMethod(MethodInfo methodInfo)
{
var parameters = methodInfo.GetParameters();
return parameters.Length == 1
&& typeof(Parent).IsAssignableFrom(parameters.First().ParameterType)
&& methodInfo.ReturnType == typeof(void);
}
public static void perform(Parent p)
{
_d[p.GetType()](p);
}
private static void action(Parent p)
{
}
private static void action(Child1 c1)
{
}
private static void action(Child2 c2)
{
}
}