2009-11-07 4 views
3

На прошлой неделе мой собеседник спросил меня, возможно ли в C# расширить общий класс из его общего параметра. Он сказал, что это возможно на C++. То, что он хотел, действительно имеет смысл. Он хотел, чтобы общий декоратор аннотировал произвольный класс с дополнительной информацией. Что-то вроде:Декоратор с базовым базовым классом

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

Так что теперь он может использовать этот общий декоратор везде вместо Т.

Наиболее близкая вещь, которую я мог бы прийти с был контейнер класса с исходным объектом, дополнительной информацией и неявное преобразование.

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 –

+1

Ну, вроде! Я ищу способ сделать этот общий декоратор, а не знать, почему общий базовый класс невозможен. – Mouk

ответ

1

Если вы можете получить все декоративные классы из какого-то базового класса, то вы можете попытаться сохранить декораторы в этом базовом классе и сделать свою информацию пригодной для восстановления. Вот пример кода, который, как гарантируется, содержит некоторые ошибки, но вы можете получить эту идею.

Если вы не можете получить, то вы должны хранить информацию в каком-то статическом классе. Но, как прокомментировал 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, чтобы исправить это, просто усложнит ситуацию: когда нужно позвонить и кем? Вы введете целый класс ошибок утечки памяти. –

+0

Спасибо, что заметили это, wcoenen. Вы совершенно правы, поэтому я обновил ответ. –

Смежные вопросы