Frage

Angenommen, wir Legacy-Klassen haben, die nicht geändert werden können:

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

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

Ich möchte ein Helfer mit einer solchen Unterschrift schreiben:

void Calc(object obj, int a);

Beachten Sie, dass das erste Argument vom Typ ‚Objekt‘. Der Testcode sollte einige so aussehen:

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

Die Frage ist, welche Implementierung Sie zusätzlich zu diesen sich vorstellen kann:

// 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);
    }
}

Danke!

War es hilfreich?

Lösung

Ich würde zum Beispiel 1, weil sie die einfachste und naheliegendste.

würde ich Beispiel 2 verwende nur, wenn Sie neue Arten von Objekten mit einem dieser beiden Methoden erwarten, und Beispiel 3 nur, wenn Sie viel (Zehner, wenn nicht Hunderte) von Objekten und Performance beginnt ein Problem zu sein.

Edit: Oder Erweiterungsmethoden, wenn Sie .Net 3

Andere Tipps

Erweiterungsmethoden verwenden, um im wesentlichen eine neue Funktion zu einem vorhandenen Typ hinzuzufügen.

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

Dies ist, wie ich würde die Lösung schreiben. Es reduziert das Risiko von Typ-Sicherheitsprobleme im Code und beseitigt Reflexion.

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;
    }
}

können Sie immer die Adapter Muster unveränderliche Vermächtnis Objekte zu implementieren, ohne alle Objekte abhängig von seiner Funktionalität zu brechen, während immer noch zu sein ableto eigene (neue) Funktionalität zum Objekt implementieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top