69 votes

Est-il possible d'implémenter les mixins en C #?

J'ai entendu dire que c'était possible avec les méthodes d'extension, mais je ne peux pas tout comprendre moi-même. J'aimerais voir un exemple spécifique si possible.

Merci!

100voto

Jon Skeet Points 692016

Cela dépend vraiment de ce que vous entendez par "mixin" - tout le monde semble avoir une idée légèrement différente. Le genre de mixin Je voudrais voir (mais qui n'est pas disponible en C #) est mise en oeuvre simple fait-par-composition:

 public class Mixin : ISomeInterface
{
    private SomeImplementation impl implements ISomeInterface;

    public void OneMethod()
    {
        // Specialise just this method
    }
}
 

Le compilateur implémenterait ISomeInterface simplement en envoyant un proxy à chaque membre pour qu'il "implicite" sauf s'il y avait une autre implémentation directement dans la classe.

Cependant, rien de tout cela n’est possible pour le moment :)

30voto

CMS Points 315406

10voto

Stefan Papp Points 418

Il existe un framework open source qui vous permet d'implémenter des mixins via C #. Jetez un coup d'œil sur http://remix.codeplex.com/ .

Il est très facile d'implémenter des mixins avec ce framework. Il suffit de consulter les exemples et les liens "Informations complémentaires" figurant sur la page.

4voto

Mauricio Scheffer Points 70470

LinFu et du Château DynamicProxy mettre en œuvre mixin. COP (Composite de la Programmation Orientée) pourrait être considéré comme faisant tout un paradigme de mixin. Ce poste de Anders Noras a des informations utiles et des liens.

EDIT: C'est possible avec C# 2.0, sans les méthodes d'extension

3voto

staafl Points 925

Vous pourrait également augmenter l'extension de la méthode d'approche pour tenir compte de l'état, dans un modèle pas contrairement à WPF propriétés attachées.

Voici un exemple avec un minimum de standard. Notez qu'aucune modification n'est nécessaire sur les classes de cibles, y compris l'ajout d'interfaces, sauf si vous avez besoin de traiter avec la classe cible polymorphically - dans ce cas, vous vous retrouvez avec quelque chose de très proche du réel de l'Héritage Multiple.

// Mixin class: mixin infrastructure and mixin component definitions
public static class Mixin
{ 
    // =====================================
    // ComponentFoo: Sample mixin component
    // =====================================

    //  ComponentFooState: ComponentFoo contents
    class ComponentFooState
    {
        public ComponentFooState() {
            // initialize as you like
            this.Name = "default name";
        }

        public string Name { get; set; }
    }

    // ComponentFoo methods

    // if you like, replace T with some interface 
    // implemented by your target class(es)

    public static void 
    SetName<T>(this T obj, string name) {
        var state = GetState<T, ComponentFooState>(component_foo_states, obj);

        // do something with "obj" and "state"
        // for example: 

        state.Name = name + " the " + obj.GetType();


    }
    public static string
    GetName<T>(this T obj) {
        var state = GetState<T, ComponentFooState>(component_foo_states, obj);

        return state.Name; 
    }

    // =====================================
    // boilerplate
    // =====================================

    //  instances of ComponentFoo's state container class,
    //  indexed by target object
    static readonly Dictionary<object, ComponentFooState>
    component_foo_states = new Dictionary<object, ComponentFooState>();

    // get a target class object's associated state
    // note lazy instantiation
    static TRet 
    GetState<TRet>(Dictionary<object, TRet> dict, object obj) 
    where TRet : new() {
        TRet ret;
        if(!dict.TryGet(obj, out ret))
            dict[obj] = ret = new TRet();

        return ret;
    }

}

Utilisation:

var some_obj = new SomeClass();
some_obj.SetName("Johny");
Console.WriteLine(some_obj.GetName()); // "Johny the SomeClass"

Notez que cela fonctionne aussi avec null cas, puisque les méthodes d'extension naturellement.

Vous pourriez aussi envisager d'utiliser un WeakDictionary mise en œuvre pour éviter les fuites de mémoire causée par la collecte de l'tenant à la classe cible de références clés.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X