2010-04-18 4 views
6

Je sais que le titre est un peu confus mais nu avec moi. (Je suis prêt pour des suggestions sur un nouveau titre lol) J'écris un TemplateEngine qui me permettra d'utiliser mon propre balisage dans des fichiers texte. Je souhaite ajouter des contrôles en tant que plugins à mesure que l'application arrive à maturité. Actuellement, j'ai une structure comme ce qui suit:Modification du type de propriété dans la classe qui implémente l'interface avec la propriété de type d'objet

interface IControl 
    string Id 
    object Value 

class Label : IControl 
    string Id 
    string Value 

class Repeater : IControl 
    string Id 
    List<IControl> Value 

Maintenant, vous verrez la partie étrange tout de suite dans la classe répéteur avec la propriété Value. J'espérais que le fait d'avoir le type Value comme objet dans l'interface me donnerait la flexibilité d'étendre les contrôles au fur et à mesure. Le compilateur n'aime pas ça et pour une bonne raison je suppose.

Conclusion: J'essaie d'obtenir que toutes les classes de contrôle implémentent la même interface mais aient des types différents pour la propriété Value.

Est-ce que quelqu'un a des suggestions pour y parvenir?

Note: Veuillez ne pas suggérer des choses comme utiliser Spark View Engine pour modéliser. Il y a une raison pour laquelle je crée du travail supplémentaire pour moi-même.

+0

Que demandez-vous? – SLaks

+0

@SLaks: LOL Désolé, je pourrais avoir besoin d'un clip vidéo pour l'expliquer un peu mieux. essayer d'entrer dans plus de détails pourrait résulter en un roman – used2could

+0

J'essaye d'obtenir toutes les classes de contrôle pour implémenter la même interface mais avoir différents types pour la propriété de valeur. – used2could

Répondre

8

Normalement, le Repeater implémenterait quelque chose de différent, comme un IItemsControl par exemple.

EDIT 1

(enlevé par souci de concision)

EDIT 2

Ah ok, vous pouvez toujours utiliser l'implémentation d'interface explicite bien sûr:

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

ouais c'est la seule autre route que je pouvais penser – used2could

+0

+1 pour comprendre ce que la merde dont je parlais même – used2could

+0

lolz ... juste la formation de mes compétences de clairvoyance: - > ... J'ai mis à jour ma réponse avec un exemple. – herzmeister

1

Non , le compilateur ne permet pas que les mêmes champs de nom soient différents t types de données autres que ce qui est défini dans l'interface dans les classes dérivées.

Les propriétés (puisque aucun champ n'est autorisé dans l'interface) doivent être implémentées dans les classes de dérivation et doivent avoir le même type de données. Donc, vous ne pouvez probablement pas le faire avec des propriétés sans déclaration explicite. Cependant, si vous faites une valeur à renvoyer par une fonction, alors cela fonctionne, mais vous devez vérifier le type de retour car les types de retour doivent correspondre pour la fonction, sinon vous obtiendrez une erreur que la fonction d'interface n'a pas été implémentée .

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"); 

[Mise à jour]
Vous devez être prudent si la définition explicite du corps des propriétés. Avoir un nom pour deux propriétés serait dangereux si la mise en œuvre n'est pas faite avec soin.

Ces deux propriétés si contiennent une définition différente, il serait inexplicable pour l'utilisation finale de l'interface et des classes.

 public IList<IControl> Value 
     object IControl.Value 

Voir cet exemple:

... 
    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; 

Vous pouvez observer que le conteneur de liste dans Repeater avoir des valeurs différentes lorsque les données sont ajoutées via IControl (en raison de la définition explicite de IContainer.Value).

+0

+1 Merci d'avoir signalé le souci de définir explicitement une propriété. – used2could

3

vous pouvez aussi utiliser les médicaments génériques:

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;} 
} 

J'aime mieux que l'idée d'interface explicite si elle est juste une valeur de retour qui doit changer. Cependant, je pense que si vous aviez plusieurs propriétés que chacune retournerait un type différent, vous ne voudriez pas avoir IControl. Au moins, je ne le ferais pas. Dans ce cas, je recommanderais les interfaces explicites.

Bien sûr, cela ne fonctionnerait pas si vous n'aviez pas accès à la source d'IControl.

Modifier: eu une faute de frappe. Fixe

+0

oui nous pourrions aussi utiliser des génériques, je n'y ai pas pensé parce que je suis soumis à un lavage de cerveau par des outils de conception d'interface utilisateur qui, pour la plupart, n'aiment pas les contrôles avec des paramètres de type génériques. ;-) – herzmeister

+0

J'ai pensé aux génériques et cela a été refusé par la direction. Quelque chose à ce sujet n'est pas facile pour les développeurs qui ne sont pas familiers avec les détails de la bibliothèque ... (Je collectionne juste un chèque) – used2could

Questions connexes