更新:@JeremyDWill 正确指出,您无法从其参数之一推导出通用类型...
< p >如果您将装饰器视为“添加新属性的子类”,则可以执行以下操作:
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;
如果您无法从装饰器进行子类化(比如需要同时支持多个装饰器),则必须使用“附加属性”等类似方法……您的装饰器类必须维护一个包含原始对象和装饰属性的字典。借助一些扩展方法,只要您事先知道被装饰对象的类型(或者愿意装饰 任何 对象),就可以使这些属性看起来像是已经定义为所装饰类的本地成员:
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;
}
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());
DataBag
继承?唯一的问题是,这样你就无法将装饰器从基本类型向下转换。 - McGarnagle