Question

Supposons que nous ayons des classes héritées, qui ne peuvent pas être modifiées:

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

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

Je veux écrire une aide avec une telle signature:

void Calc(object obj, int a);

Notez que le premier argument est de type 'objet'. Le code de test devrait ressembler à ceci:

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

La question est de savoir quelle mise en oeuvre vous pouvez imaginer en plus de celles-ci:

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

Merci!

Était-ce utile?

La solution

Je choisirais l'exemple 1, car c'est le plus simple et le plus évident.

Je n’utiliserais l’Exemple 2 que si vous attendez de nouveaux types d’objets avec l’une de ces méthodes et l’exemple 3 uniquement si vous avez beaucoup d’objets (des dizaines sinon des centaines) et que les performances commencent à poser problème.

Édition: ou méthodes d’extension si vous êtes .Net 3

Autres conseils

Utilisez des méthodes d'extension pour ajouter une nouvelle fonction à un type existant.

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

Voici comment j'écrirais la solution. Cela réduit le risque de problèmes de sécurité de type dans le code et élimine les réflexions.

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

vous pouvez toujours utiliser le modèle d'adaptateur pour implémenter les objets hérités non modifiables, sans briser tous les objets dépendant de ses fonctionnalités, tout en restant capable d'implémenter votre propre (nouvelle) fonctionnalité pour cet objet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top