2009-03-06 2 views
1

Предположим, что мы имеем унаследованные классы, которые не могут быть изменены:C#. Добавить полиморфизм для унаследованного кода

class Foo 
{ 
    public void Calculate(int a) { } 
} 

class Bar 
{ 
    public void Compute(int a) {} 
} 

Я хочу написать помощника с такой подписью:

void Calc(object obj, int a); 

Обратите внимание, что первый аргумент имеет тип «объект». Тестовый код должен быть какой-то вроде этого:

ExampleX.Calc((object)new Foo(), 0); 
ExampleX.Calc((object)new Bar(), 0); 

вопрос, что реализация вы можете себе представить, в дополнение к ним:

// Using If/then 
class Example1 
{ 
    public static void Calc(object obj, int a) 
    { 
     if (obj is Foo) 
      ((Foo)obj).Calculate(a); 
     else if (obj is Bar) 
      ((Bar)obj).Compute(a); 
    } 
} 

// Using reflection 
class Example2 
{ 
    private static Dictionary<Type, MethodInfo> _methods = new Dictionary<Type, MethodInfo>(); 

    static Example2() 
    { 
     _methods.Add(typeof(Foo), typeof(Foo).GetMethod("Calculate")); 
     _methods.Add(typeof(Bar), typeof(Bar).GetMethod("Compute")); 
    } 

    public static void Calc(object obj, int a) 
    { 
     _methods[obj.GetType()].Invoke(obj, new object[] { a }); 
    } 
} 

// Using delegates 
class Example3 
{ 
    private delegate void CalcDelegate(object obj, int a); 

    private static Dictionary<Type, CalcDelegate> _methods = new Dictionary<Type, CalcDelegate>(); 

    static Example3() 
    { 
     _methods.Add(typeof(Foo), (o, a) => ((Foo)o).Calculate(a)); 
     _methods.Add(typeof(Bar), (o, a) => ((Bar)o).Compute(a)); 
    } 

    public static void Calc(object obj, int a) 
    { 
     _methods[obj.GetType()](obj, a); 
    } 
} 

// Using Reflection + overloaded methods 
class Example4 
{ 
    private delegate void CalcDelegate(object obj, int a); 

    public static void Calc(object obj, int a) 
    { 
     Type[] types = new Type[] { 
      obj.GetType(), typeof(int) 
     }; 

     typeof(Example4).GetMethod("Calc", types).Invoke(null, new object[] { obj, a }); 
    } 

    public static void Calc(Foo obj, int a) 
    { 
     obj.Calculate(a); 
    } 

    public static void Calc(Bar obj, int a) 
    { 
     obj.Compute(a); 
    } 
} 

Спасибо!

+0

Вы пытаетесь получить, по сути, вызов виртуальной функции? – Qwertie

+0

Нет, я не называю виртуальную функцию. Но что бы это изменило? – alex2k8

ответ

0

Я бы пошел, например, 1, потому что его самый простой и наиболее очевидный.

Я бы использовал пример 2, только если вы ожидаете новых типов объектов с одним из этих двух методов, а пример 3, только если у вас есть много (десятки, если не сотни) объектов, и производительность начинает быть проблемой.

Edit: Или удлинительные методы, если вы .Net 3

3

Используйте методы расширения, чтобы по существу добавить новую функцию к существующему типу.

http://msdn.microsoft.com/en-us/library/bb383977.aspx

+0

Расширение, не добавляющее полиморфизм. Я добавил Example4, который использует подобный подход. Код расширения, который должен быть почти таким же. – alex2k8

2

Это, как я хотел бы написать решение. Это уменьшает риск проблем с безопасностью типа в коде и устраняет отражение.

class Example2 
{ 
    private static Dictionary<Type, Action<object,int>> _methods = new Dictionary<Type, Action<object,int>>(); 

    static Example2() 
    { 
     Add<Foo>((f,a) => f.Calculate(a)); 
     Add<Bar>((b,a) => b.Compute(a)); 
    } 

    public static void Calc<TSource>(TSource source, int a) 
    { 
     _methods[typeof(TSource)](source,a); 
    } 

    public static void Add<TSource>(Action<TSource,int> del) 
    { 
     Action<object,int> wrapper = (x,i) => { del((TSource)x, i); }; 
     _methods[typeof(TSource)] = wrapper; 
    } 
} 
1

вы всегда можете использовать adapter pattern для реализации неизменных унаследованных объектов, не нарушая каких-либо объектов, зависящих от его функциональности, в то же время ableto реализовать свой собственный (новый) для объекта.

 Смежные вопросы

  • Нет связанных вопросов^_^