2010-04-18 7 views
6

Ich weiß, der Titel ist ein bisschen verwirrend, aber mit mir blank. (Ich bin für Vorschläge auf einen neuen Titel lol) Ich schreibe eine TemplateEngine, die es mir erlaubt, mein eigenes Markup in textbasierten Dateien zu verwenden. Ich möchte Kontrollen als Plugins hinzufügen, wenn die Anwendung reift. Zur Zeit habe ich eine Struktur wie die folgenden bekommen:Ändern des Eigenschaftstyps in der Klasse, die die Schnittstelle mit Objekttyp-Eigenschaft implementiert

interface IControl 
    string Id 
    object Value 

class Label : IControl 
    string Id 
    string Value 

class Repeater : IControl 
    string Id 
    List<IControl> Value 

Jetzt werden Sie den seltsamen Teil sofort in der Repeater-Klasse mit der Value-Eigenschaft sehen. Ich hatte gehofft, dass die Möglichkeit, den Werttyp als Objekt in der Schnittstelle zu verwenden, mir die Flexibilität geben würde, die Steuerelemente zu erweitern, während ich weitermache. Der Compiler mag das nicht und ich denke, aus gutem Grund.

Fazit: Ich versuche, alle Steuerelementklassen die gleiche Schnittstelle zu implementieren, aber verschiedene Typen für die Value-Eigenschaft.

Hat jemand irgendwelche Vorschläge, wie dies zu erreichen ist?

Hinweis: Bitte gehen Sie nicht auf Dinge wie Spark View Engine zum Templating vor. Es gibt einen Grund, warum ich zusätzliche Arbeit für mich selbst erschaffe.

+0

Wonach fragen Sie? – SLaks

+0

@SLaks: LOL Entschuldigung, ich könnte einen Videoclip brauchen, der es ein wenig besser erklärt. Der Versuch, in mehr Details zu gehen, könnte zu einem neuen – used2could

+0

führen. Ich versuche, alle Steuerklassen zu erhalten, um dieselbe Schnittstelle zu implementieren, aber unterschiedliche Typen für die Eigenschaft Value. – used2could

Antwort

8

Normalerweise würde die Repeater etwas anderes implementieren, wie zum Beispiel eine IItemsControl.

EDIT 1

(entfernt der Kürze halber)

EDIT 2

Ah okay, du immer explizite Schnittstellenimplementierung natürlich verwenden können:

interface IControl 
{ 
    string Id { get; set; } 
    object Value { get; set; } 
} 

class Label : IControl 
{ 
    public string Id { get; set; } 
    public string Value { get; set; } 

    object IControl.Value 
    { 
     get { return this.Value; } 
     set { this.Value = (string)value; } 
    } 
} 

class Repeater : IControl 
{ 
    public string Id { get; set; } 
    public IList<IControl> Value { get; set; } 

    object IControl.Value 
    { 
     get { return this.Value; } 
     set { this.Value = (IList<IControl>)value; } 
    } 
} 
+0

yeah das ist die einzige andere Route, die ich denken konnte – used2could

+0

+1 für herauszufinden, was der Mist, über den ich gerade sprach – used2could

+0

lolz ... nur meine Hellsichtigkeit Fähigkeiten training: - > ... Ich habe meine Antwort mit einem Beispiel aktualisiert. – herzmeister

1

Nein , der Compiler erlaubt nicht, dass Felder gleichen Namens differentiell sind t andere Datentypen als das, was in abgeleiteten Klassen in der Schnittstelle definiert ist.

Die Eigenschaften (da in der Schnittstelle keine Felder erlaubt sind) sollten in den abgeleiteten Klassen implementiert werden und sie müssen denselben Datentyp haben. So können Sie es wahrscheinlich nicht mit Eigenschaften ohne explizite Deklaration tun.

Wenn Sie jedoch Wert von einer Funktion zurückgegeben werden, funktioniert es, aber Sie müssen den Rückgabetyp überprüfen, da die Rückgabetypen für die Funktion übereinstimmen sollten, andernfalls erhalten Sie Fehler, dass Schnittstelle nicht implementiert wurde .

interface IControl 
    { 
     object Value(); 
    } 
    class A : IControl 
    { 
     string m_value = string.Empty; 
     public object Value() { return m_value; } 
    }; 
    class B : IControl 
    { 
     List<IControl> m_value = new List<IControl>(); 
     public object Value() { return m_value; } 
    }; 
    .... 
    object o = new B().Value(); 
    if (o is List<IControl>) 
     MessageBox.Show("List"); 

[Update]
Sie müssen vorsichtig sein, wenn dies ausdrücklich in den Körper der Eigenschaften zu definieren. Ein Name für zwei Eigenschaften wäre gefährlich, wenn die Implementierung nicht sorgfältig durchgeführt wird.

Diese beiden Eigenschaften, wenn sie unterschiedliche Definitionen enthalten, wären für die endgültige Verwendung der Schnittstelle und der Klassen unerklärlich.

 public IList<IControl> Value 
     object IControl.Value 

dieses Beispiel Siehe:

... 
    class Repeater : IControl 
    { 
     List<IControl> m_Value = new List<IControl>(); 
     public IList<IControl> Value 
     { 
      get { return this.m_Value; } 
      set { this.m_Value = (IList<IControl>)value; } 
     } 
     object IControl.Value 
     { 
      get 
      { 
       return this.m_Value; 
      } 
      set 
      { 
       this.m_Value = new List<IControl>(); 
       this.m_Value.Add(new Label()); 
       this.m_Value.AddRange((List<IControl>)value); 
      } 
     } 
    } 
    ... 
    Repeater b = new Repeater(); 
    IControl i = b; 
    List<IControl> list = new List<IControl>(); 
    list.Add(new Repeater()); 
    i.Value = list; 

Sie können beobachten, dass die Containerliste in Repeater unterschiedliche Werte haben, wenn Daten über IControl hinzugefügt wird (wegen der expliziten Definition von IContainer.Value).

+0

+1 Danke, dass Sie auf das Problem hingewiesen haben, eine Eigenschaft explizit zu definieren. – used2could

3

Sie auch Generika verwenden:

interface IControl<T> 
{ 
    string ID{get;set;} 
    T Value{get;set;} 
} 

class SomeControl : IControl<string> 
{ 
    public string ID{get;set} 
    public string Value{get;set;} 
} 

class SomeOtherControl : IControl<int> 
{ 
    public string ID{get;set} 
    public int Value{get;set;} 
} 

Ich mag diese besser als die explizite Idee Schnittstelle, wenn es nur einen Rückgabewert ist, der geändert werden muss. Ich denke jedoch, wenn Sie mehrere Eigenschaften hätten, die jeweils einen anderen Typ zurückgeben, würden Sie IControl nicht wollen. Zumindest würde ich nicht. In diesem Fall würde ich die expliziten Schnittstellen empfehlen.

Natürlich würde dies nicht funktionieren, wenn Sie keinen Zugriff auf die Quelle von IControl hätten.

Edit: hatte einen Tippfehler. Fest

+0

ja könnten wir auch Generika verwenden, ich habe nicht darüber nachgedacht, weil ich von UI-Design-Tools, die meist keine Kontrollen mit generischen Typparametern mögen, einer Gehirnwäsche unterzogen wurde. ;-) – herzmeister

+0

Ich dachte über Generika nach und es wurde vom Management abgelehnt. Etwas ist für Entwickler, die mit den Details der Bibliothek nicht vertraut sind, nicht einfach ... (Ich sammle nur einen Scheck) – used2could

Verwandte Themen