Is it possible to implement mixins in C#?

前端 未结 9 639
感动是毒
感动是毒 2020-11-29 17:50

I\'ve heard that it\'s possible with extension methods, but I can\'t quite figure it out myself. I\'d like to see a specific example if possible.

Thanks!

9条回答
  •  广开言路
    2020-11-29 18:39

    You could also augment the extension method approach to incorporate state, in a pattern not unlike WPF's attached properties.

    Here is an example with minimum boilerplate. Note that no modification are required on the target classes, including adding interfaces, unless you need to deal with the target class polymorphically - in which case you end up with something very close to actual Multiple Inheritance.

    // 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(this T obj, string name) {
            var state = GetState(component_foo_states, obj);
    
            // do something with "obj" and "state"
            // for example: 
    
            state.Name = name + " the " + obj.GetType();
    
    
        }
        public static string
        GetName(this T obj) {
            var state = GetState(component_foo_states, obj);
    
            return state.Name; 
        }
    
        // =====================================
        // boilerplate
        // =====================================
    
        //  instances of ComponentFoo's state container class,
        //  indexed by target object
        static readonly Dictionary
        component_foo_states = new Dictionary();
    
        // get a target class object's associated state
        // note lazy instantiation
        static TState
        GetState(Dictionary dict, object obj) 
        where TState : new() {
            TState ret;
            if(!dict.TryGet(obj, out ret))
                dict[obj] = ret = new TState();
    
            return ret;
        }
    
    }
    

    Usage:

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

    Note that it also works with null instances, since extension methods naturally do.

    You might also consider using a WeakDictionary implementation to avoid memory leaks caused by the collection's holding on to target class references as keys.

提交回复
热议问题