2010-04-29 8 views
10

ist es möglich, einfach und dynamisch ein objekt dekorieren?dynamisch dekorieren von objekten in C#

zum Beispiel, sagen wir, ich habe eine List<PointF>. Diese Liste ist eigentlich ein Diagramm der Sinusfunktion. Ich würde gerne diese Punkte durchgehen und jedem Punkt eine Flagge hinzufügen, ob es ein Gipfel ist oder nicht.

aber ich möchte nicht eine neue erweiterte SpecialPointF oder was auch immer, die eine boolesche Eigenschaft hat.

Beurteilen Sie mich alles, was Sie für faul wollen, aber Faulheit ist wie genial Ideen geboren (auch schlechte Ideen)

Edit: Ich werde Boxen Lösungen sowie alle interessanten Hack akzeptieren Sie können sich mit. es gibt nichts, was mich daran hindern könnte, abzuleiten. Ich will nur wissen, ob es mehr Spaß macht.

+1

Ich gab Ihnen nur +1 für Ihren Abschlusssatz. Nicht wirklich sicher über eine Antwort auf Ihre Frage, obwohl. –

Antwort

4

Wenn es einen Weg gibt, den Sie pro Punkt berechnen können, müssen Sie kein Flag hinzufügen, Sie können eine extension Methode verwenden, ohne sie zu erweitern.

So etwas wie PointF.isPeak();

Es funktioniert so etwas wie:

public static class Extensions 
{ 
    public static bool isPeak (this PointF p) 
    { 
     do crazy math... 

     return result; 
    } 
} 

Und voilà, haben Sie Ihre Berechnung in Ihrer PointF Klasse.

Übrigens muss die öffentliche statische Klasse im äußersten Bereich sein, kann nicht geschachtelt werden.

+1

+1 sagen. Hervorragender Vorschlag, obwohl "isPeak" nicht mit .NET-Namenskonventionen konsistent ist (das erste Zeichen sollte groß geschrieben werden) –

+0

Das ist eine fantastische Idee. Ich liebe es. –

+0

@Francisco: Extension-Methode ist eine gute Idee, aber in diesem Fall wie weiß ein Punkt, wenn es der Höhepunkt in einer Serie ist, die es nicht enthält? Es sei denn, der Punkt enthält einen Zeiger auf die Serie, die Teil von ... ist. –

5

Nein, es gibt keine Möglichkeit (genau) zu tun, wonach Sie fragen.

Wenn Sie C# 3.0+ verwenden, können Sie anonyme Typen verwenden, vorausgesetzt, dass Sie die Informationen nicht außerhalb Ihrer Funktion verfügbar machen möchten.

var decoratedList = sourceList.Select(pt => new 
        { 
         IsPeak = GetIsPeak(pt), 
         Point = pt 
        }).ToList(); 

Dadurch erhalten Sie ein neues Objekt List<T>. Dies kann sehr gut Ihr Problem nicht lösen, da Sie nicht diese außerhalb einer einzigen Funktionsaufruf erweitern können und Sie erstellen eine neue Liste anstatt Bearbeiten eines vorhandenen, aber hoffentlich das hilft.

+0

Das ist eine coole Idee. Ich habe noch keine anonymen Typen benutzt, also habe ich nicht einmal darüber nachgedacht. wir sind ziemlich cool mit der Verwendung der neuesten C#, also ist es kein Problem. –

+0

@Oren: Sie sind nett, aber der größte Nachteil ist nicht in der Lage, sie außerhalb Ihrer Funktion zu belichten. Wenn Sie das tun müssten, müssten Sie Ihre eigene einfache Wrapper-Klasse mit einer ähnlichen Signatur erstellen und dann einfach 'new WrapperClass {...' anstatt nur 'new {...' –

2

Nein ist es nicht möglich.

Nächstes wird nur ein

var decorationData = new Dictionary <Object, bool> 

erstellen und dann dort Ihre Werte zu speichern. Keine Notwendigkeit, den Typ direkt zu erweitern. Sie können sogar eine Erweiterungsmethode verwenden, um die gespeicherten Daten zuzugreifen, die es dann aussehen wie eine direkte Eigenschaft des Objekts ist.

public static class PointFPeakExtensions 
{ 
    private static var decorationData = new Dictionary <PointF, bool> 

    public static bool IsPeak (this PointF point) 
    { 
     return decorationData[point]; 
    } 
    public static void SetPeak (this PointF point, bool isPeak) 
    { 
     decorationData[point] = isPeak; 
    } 
} 

Und mit denen Sie Ihre edit:

Sie auch diese mit einer generischen Art lösen zu können, die als Nullable-Typ implementiert wird in den Klassenbibliotheken nur die Dekoration Daten und die genannte Art (In gleicher Weise enthält). Wie dem auch immer noch bedeutet, dass Sie die Unterschriften an den Stellen ändern müssen Sie die Art verwenden (was nicht wahrscheinlich ist, was Sie tun möchten, wenn für Dekorateur suchen).

3

Es könnte möglich sein, dies zu tun, um das neue dynamic Schlüsselwort und ExpandoObject Konstrukt in C# 4.0, aber ich habe noch nicht mit ihm Erfahrung aus erster Hand. Wie ich verstehe es war leicht genau dieses Problem zu lösen, erstellt, so können Sie

dynamic something = new ExpandoObject(); 
something.Anything = "whatever you want"; 

sagen, dass ich glauben es möglich ist, Typen dynamisch zu erweitern bestehende, aber es könnte erfordern eine neue Unterklasse zu schaffen, die die Niederlage würde ganzer Zweck der Übung.

Eine nahezu identische Lösung kann mit Erweiterungsmethoden erstellt werden. Die ExpandoObject ist intern als Dictionary implementiert, aber es fügt die klassische native Syntax hinzu.

class Program { 

    static void Main(string[] args) 
    { 
     PointF p = new PointF(0, 0); 

     p.SetFlag(true); 

     if (p.GetFlag()) 
     Console.WriteLine("win"); 
    } 

} 

public static class Extensions 
{ 
    private static Dictionary<PointF, bool> flags = new Dictionary<PointF, bool>(); 
    public static bool GetFlag(this PointF key) 
    { 
     return flags[key]; 
     //OR return flags.ContainsKey(key) ? flags[key] : false; 
    } 

    public static void SetFlag(this PointF key, bool val) 
    { 
     flags[key] = val; 
    } 
} 
+0

statt p.SetFlag meinst du, Extensions aufzurufen.SetFlag (p, true); ? –

+0

Nein, Erweiterungsmethoden ermöglichen es Ihnen, Anrufe zu tätigen, die so "nativ" aussehen. Es ruft automatisch 'Extensions.SetFlag (p, true)' für Sie auf. –