具有泛型基类的装饰器 [英] Decorator with generic base class

查看:99
本文介绍了具有泛型基类的装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的一位同事上周问我是否有可能用C#从泛型参数中扩展泛型类。他说在C ++中是可能的。
他想要的东西实际上是有意义的。他想要一个通用的装饰器来注释一个任意的类和附加信息。例如:

 公共类Decorator< T> :T 
{
public object AdditionalInformation {get:set;}
}


$ b $所以他现在可以使用这个泛型装饰器而不是T。



我可以使用的最类似的东西是一个带有原始对象的容器类,附加信息和一个隐式转换。

 公共类装饰器< T> 
{
私人只读T _instance;
public Decorator(T实例)
{
_instance = instance;
}

public T实例
{
get {return _instance; }
}
公共对象AdditionalInformation {get;组; }

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

但这不一样,因为隐式转换是只有一种方法。例如,他不能将它用作方法的返回类型,因为在隐式转换后附加信息会丢失。



有没有人有更好的主意? / p>如果你可以从某个基类派生出所有可分类的类,那么你可以尝试在该基类中存储装饰器,并使其信息可恢复。这里是示例代码,保证包含一些错误,但你可以明白。

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

}

公共类装饰器< T> T:class,Decorable
{
private只读T _instance;
public Decorator(T实例)
{
_instance = instance;
instance.AddDecorator(this);
}

public T实例
{
get {return _instance; }
}

公共对象AdditionalInformation {get;组; }
}
//像这样使用
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)
{
//这里必须是双TryGetValue,但是我把它留给你添加它
return(D)instance [obj] [typeof(D)];
}

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

}

// Decorator< T>代码保持不变,但没有类型约束


A co-worker of mine asked me last week if it were possible in C# to extend a generic class from its generic parameter. He said it was possible in C++. What he wanted makes actually sense. He wanted a generic decorator to annotate an arbitrary class with additional information. Something like:

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

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

The most similar thing I could come with was a container class with the original object, the 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 the implicit conversion is only one way. He cannot use it, for example, as a return type of a method because the additional information would be lost after he implicit conversion.

Does anybody have a better idea?

解决方案

If you can derive all decorable classes from some base class, then you can try to store decorators in that base class and make its info recoverable. Here is sample code that is guaranteed to contain some errors, but you can get the idea.

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>>();

If you cannot derive, then you must store info in some static class. But, as wcoenen commented, you would need to clear that info or you'd get memory leaks. Clearing is error prone and not always possible, so it's better to go with the first approach. For example (not thread safe, you must add locking if you plan to use it in multithreaded apps):

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

这篇关于具有泛型基类的装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆