2009-05-21 5 views
0

J'écris un wrapper pour le contrôle WinForms ComboBox qui va me permettre de remplir la liste déroulante avec une liste <T>, et a une propriété Selected qui retourne un élément de type T (ou null si rien de sélectionné).ComboBox générique avec propriétés nommées automatiquement

Plutôt que d'avoir une propriété Selected, j'aimerais qu'elle soit nommée en fonction du type générique automatiquement. Par exemple:

  • MyDropDownList <utilisateur> aurait une propriété SelectedUser
  • MyDropDownList < Département > aurait une propriété SelectedDepartment
  • MyDropDownList < d'État > aurait une propriété SelectedState

Avec LINQ , Je peux créer des types anonymes pendant le groupement, comme ceci:

var usersByGender = users 
    .GroupBy(x => x.Gender) 
    .Select(group => new {Gender = group.Key, List = group.ToList()}); 

Ce qui se traduira par une liste de type anonyme généré contenant une propriété de genre et la liste <utilisateur> qui sont détectables par IntelliSense. La question est, puis-je en quelque sorte le faire avec des propriétés dans une classe générique?

EDIT: Je réalise maintenant que je demande essentiellement "method_missing" en C# 3.0, ce qui est probablement impossible. Je suis ouvert aux suggestions, cependant.

+0

Souhaitez-vous générer un nom d'appel de propriété Selected à l'exécution, nommé d'après la classe d'élément dans la liste déroulante? Ou souhaitez-vous que cela change au moment de la conception? – ChrisBD

+0

Il est actuellement caché au moment du design, mais j'aimerais pouvoir y accéder via le code. Ma solution actuelle avec juste la propriété "Selected" fonctionne très bien, je pense juste que le code lirait plus facilement s'il était "Selected" + typeof (T) .Name –

Répondre

1

Je ne pense pas que vous pouvez le faire. La seule approche qui a même une faible chance de travailler serait de créer une sorte de méthode d'usine qui a créé le type et l'a renvoyé. Fondamentalement, votre type générique devient une classe de base et IL est écrit dynamiquement en créant une classe concrète qui hérite du générique mais avec la nouvelle propriété ajoutée. Bien sûr, l'objet renvoyé serait vraiment anonyme et vous ne pourriez accéder qu'à à travers la réflexion puisque vous n'auriez pas un type à fait castée:

public static class CrazyFactory 
{ 
    public static object CreateTypedComboList<T>() 
    { 
      //magic happens 
      return object; 
    } 
} 

Son utilisation serait alors besoin

object userCombo = CrazyFactory.CreateTypedComboList<User>(); 
PropertyInfo selectedUserProperty = userCombo.GetType().GetProperty("SelectedUser"); 
selectedUserProperty.SetValue(userCombo, user); 

ce qui est à peine un pas à partir d'une simple propriété T SelectedItem. D'un bref coup d'oeil, il semble que ce type de chose sera plus facile lorsque C# 4.0 nous apporte des types dynamiques. En mettant en œuvre l'interface IDynamicObject il sera possible d'attraper tous les appels à des propriétés non définies et les manipuler de sorte que vous pouvez utiliser la logique comme ce qui suit:

public override MetaObject GetMember(GetMemberAction action, MetaObject[] args) 
{ 
    //not sure on the real property name here... 
    string actionName = action.Name; 

    if (actionName = "Selected" + typeof(T).Name) 
    { 
      return SelectedItem; //in some MetaObject wrapper 
    } 
} 

J'ai suivi this article et n'ont pas encore touché moi-même dynamique, mais il semble que ce que vous voulez soit possible. Je ne le ferais toujours pas cependant - vous n'obtiendrez pas Intellisense et il semble être une méthode fragile et compliquée pour définir la fonctionnalité.

1

Non, vous ne pouvez pas faire cela. L'idée derrière les types génériques est qu'ils s'appliquent également à tous les types qui peuvent être spécifiés dans le paramètre générique. Ce ne serait pas le cas si toutes les spécialisations étaient autorisées à déclarer des membres nommés différemment.

Questions connexes