更新:@JeremyDWill正确地指出,你不能从它的一个参数推导出泛型类型...
如果你想装饰作为一个“子类,增加了新的属性”,你可以这样做:
MyDecorator<OtherClass>
的
MyDecorator<DataBag>
public class MyDecorator<T> : T
{
public int MyDecoratorProperty1 { get; set; }
public int MyDecoratorProperty2 { get; set; }
}
然后你就可以创建实例,等现有的属性是可访问的,因为
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; // 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());
通常,装饰器都从一个通用接口继承。在这种情况下,该接口会是什么?如果它是动态的,那么装饰者可能不适合。 –
你有没有考虑过装饰器*从'DataBag'继承*?唯一的问题是你不能从装饰者向下投射基础类型。 – McGarnagle
@dbaseman我最初使用了继承,但很快就遇到了需要很多具有稍微不同属性和方法的类的情况。 – Anton