更新:@JeremyDWill 正确地指出,您不能从其参数之一派生泛型类型...
如果您将装饰器视为“添加新属性的子类”,您可以执行以下操作:
public class MyDecorator<T> : T
{
public int MyDecoratorProperty1 { get; set; }
public int MyDecoratorProperty2 { get; set; }
}
然后您可以创建MyDecorator<DataBag> 和MyDecorator<OtherClass> 等的实例。现有属性是可访问的,因为MyDecorator<> 特定于泛型参数的类型,并且派生自该类。
您可以创建一个包含装饰对象的包装器:
public class MyDecorator<T>
{
public MyDecorator(T decoratedObject)
{
this.DecoratedObject = decoratedObject;
}
public T DecoratedObject { get; private set; }
public int MyDecoratorProperty1 { get; set; }
public int MyDecoratorProperty2 { get; set; }
}
优点是访问装饰属性很容易:myObj.MyDecoratorProperty1。缺点是您现在必须通过 DecoratedObject 成员才能访问基础对象:
DataBag bag = new DataBag("", null, null);
MyDecorator<DataBag> deco = new MyDecorator<DataBag>(bag);
deco.DecoratedObject.Height = 2;
如果你不能从装饰子类中继承(比如说你需要同时支持多个装饰器),你将不得不做一个“附加属性”之类的事情......你的装饰器类必须保留一个原始对象和修饰属性的字典。使用一些扩展方法,您可以使这些属性“看起来”像被修饰类的本地成员,只要您知道预先修饰的类型(或愿意修饰 any 对象):
public static class AttachedDecorator
{
private class Properties
{
public int MyDecoratorProperty1 { get; set; }
public int MyDecoratorProperty2 { get; set; }
}
private static Dictionary<object, Properties> map = new Dictionary<object, Properties>();
public static int GetMyDecoratorProperty1(object obj)
{
Properties props;
if (map.TryGetValue(obj, out props))
{
return props.MyDecoratorProperty1;
}
return -1; // or some value that makes sense if the object has no decorated property set
}
public static int GetMyDecoratorProperty2(object obj) { /* ... */ }
public static void SetMyDecoratorProperty1(object obj, int value)
{
Properties props;
if (!map.TryGetValue(obj, out props))
{
props = new Properties();
map.Add(obj, props);
}
props.MyDecoratorProperty1 = value;
}
public static void SetMyDecoratorProperty2(object obj, int value) { /* ... */ }
}
public static class DecoratorExtensions
{
private static int GetMyDecoratorProperty1(this object obj)
{
return AttachedDecorator.GetMyDecoratorProperty1(obj);
}
private static void SetMyDecoratorProperty1(this object obj, int value)
{
return AttachedDecorator.GetMyDecoratorProperty1(obj, value);
}
// ...
}
您的代码可能如下所示:
DataBag myData = new DataBag();
myData.SetMyDecoratorProperty1(7);
Console.WriteLine("prop1: {0}", myData.GetMyDecoratorProperty1());