Decorator with a base base class

One of my co-workers asked me last week if C # could extend the general class from its general parameter. He said that this is possible in C ++. What he wanted really makes sense. He wanted a general decorator to annotate an arbitrary class with additional information. Sort of:

pubic class Decorator<T> : T
{
  public object AdditionalInformation {get:set;}
}

So now he can use this generic decorator everywhere instead of T.

The closest thing I could come with was a container class with the source object, additional information, and an implicit conversion.

public class Decorator<T>
{
    private readonly T _instance;
    public Decorator(T instance)
    {
        _instance = instance;
    }

    public T Instance
    {
        get { return _instance; }
    }
    public object AdditionalInformation { get; set; }

    public static implicit operator T(Decorator<T> deco)
    {
        return deco._instance;
    }
}

But this is not the same, because implicit conversion is only one way. He cannot use it, for example, as a return type of a method, because additional information will be lost after its implicit conversion.

- ?

+3
1

- , . , , .

public class Decorable
{
    Dictionary<Type,object> decors = new Dictionary<Type,object>();
    public void AddDecorator<D>(D decor) { decors[typeof(D)] = decor; }
    public D GetDecorator<D>()
    {
        object value;
        if (decors.TryGetValue(typeof(D), out value))
            return (D)value;
        else
            return default(D);
    }

}

public class Decorator<T> where T: class, Decorable
{
    private readonly T _instance;
    public Decorator(T instance)
    {
        _instance = instance;
        instance.AddDecorator(this);
    }

    public T Instance
    {
        get { return _instance; }
    }

    public object AdditionalInformation { get; set; }
}
// use it like this
Decorator<MyClass> myDecor = myObj.GetDecorator<Decorator<MyClass>>();

, - . , wcoenen, . , . ( , , ):

static public class Decorators
{
    static Dictionary<object,Dictionary<Type,object>> instance = new Dictionary<object,Dictionary<Type,object>>();
    public static void AddDecorator<T,D>(this T obj, D decor)
    {
        Dictionary<Type,object> d;
        if (!instance.TryGetValue(obj, out d))
        {
            d = new Dictionary<Type,object>();       
            instance.Add(obj, d);
        }
        d[typeof(D)]=decor;
    }

    public static D GetDecorator<T,D>(this T obj)
    {
        // here must be double TryGetValue, but I leave it to you to add it  
        return (D) instance[obj][typeof(D)];
    }

    public static T ClearDecorators(this T obj) { instance.remove(obj); }

}

// Decorator<T> code stays the same, but without type constraint
+1

Source: https://habr.com/ru/post/1722226/


All Articles