Update: @JeremyDWill Recht darauf hingewiesen, dass Sie nicht einen generischen Typ von einem seiner Parameter ...
Wenn Sie denken, der Dekorateur als „Unterklasse, die neue Eigenschaften hinzufügt“ ableiten können, Sie etwas tun könnte wie:
public class MyDecorator<T> : T
{
public int MyDecoratorProperty1 { get; set; }
public int MyDecoratorProperty2 { get; set; }
}
Dann können Sie Instanzen von
MyDecorator<DataBag>
erstellen, und
MyDecorator<OtherClass>
usw. die vorhandenen Eigenschaften zugänglich sind, weil die
MyDecorator<>
auf die Art des generischen Argument spezifisch ist, und leitet sich von dieser Klasse.
Sie können einen Wrapper erstellen, die das eingerichtete Objekt enthält:
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; }
}
Der Vorteil ist, dass auf den geschmückten Eigenschaften immer einfach ist: myObj.MyDecoratorProperty1
. Der Nachteil ist, dass man jetzt durch das DecoratedObject
Mitglied gehen, um das Basis-Objekt zu erhalten:
DataBag bag = new DataBag("", null, null);
MyDecorator<DataBag> deco = new MyDecorator<DataBag>(bag);
deco.DecoratedObject.Height = 2;
Wenn Sie nicht aus der Unterklasse können deco (Sie müssen mehrere Dekorateure zu einer Zeit, unterstützen, sagen), Sie müssen etwas wie eine "angefügte Eigenschaft" tun ... Ihre Dekoratorklasse würde ein Wörterbuch der ursprünglichen Gegenstände und der verzierten Eigenschaften behalten müssen. Mit wenigen Erweiterungsmethoden, können Sie diese Eigenschaften „Look“ wie native Mitglieder der dekorierten Klasse machen, solange Sie die Typen wissen immer im Voraus eingerichtet (oder bereit sind, jedes Objekt zu dekorieren):
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);
}
// ...
}
Code könnte dann wie folgt aussehen:
DataBag myData = new DataBag();
myData.SetMyDecoratorProperty1(7);
Console.WriteLine("prop1: {0}", myData.GetMyDecoratorProperty1());
normalerweise erben Dekoratoren alle von einer gemeinsamen Schnittstelle. Was wäre in diesem Fall die Schnittstelle? Wenn es dynamisch ist, dann ist vielleicht Dekorateur nicht die richtige Lösung. –
Haben Sie darüber nachgedacht, den Dekorator * von 'DataBag' erben zu lassen? Das einzige Problem besteht dann darin, dass Sie vom Dekorator nicht den Basistyp abwandeln können. – McGarnagle
@dbaseman Ich habe zuerst die Vererbung benutzt, bin aber sehr schnell in eine Situation geraten, in der viele Klassen mit leicht unterschiedlichen Eigenschaften und Methoden benötigt wurden. – Anton