2009-11-07 54 views
3

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

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

所以他现在可以随处使用,而不是T.这个一般装饰

最类似的事情,我可以跟是一个容器类与原来的对象,附加信息和隐式转换。

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

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

有没有人有更好的主意?

+1

类似的问题:http://stackoverflow.com/questions/1420581/inheritance-on-a-constrained -generic-type-parameter – 2009-11-07 23:44:40

+1

好吧,那种!我正在寻找一种方法来使这个通用装饰器,而不是知道为什么泛型基类是不可能的。 – Mouk 2009-11-08 00:03:24

回答

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

保持对象与装饰器映射的静态类将导致装饰对象永远不会被垃圾收集。添加一个RemoveDecorator来解决这个问题只会让事情变得更复杂:什么时候应该调用它以及由谁来调用?你会介绍一整类的内存泄漏错误。 – 2009-11-08 11:11:52

+0

感谢您的注意,wcoenen。你是完全正确的,所以我已经更新了答案。 – 2009-11-08 16:13:37

相关问题