具有自动命名属性的通用ComboBox

时间:2009-05-21 14:26:42

标签: c# generics .net-3.5 user-controls

我正在为WinForms ComboBox控件编写一个包装器,它允许我使用List< T>填充下拉列表,并且具有一个Selected属性,该属性返回T类型的项目(如果没有选择,则返回null)。

我希望自动根据泛型类型命名,而不是拥有Selected属性。例如:

  • MyDropDownList<使用者>会有一个SelectedUser属性
  • MyDropDownList<&系GT;会有一个SelectedDepartment属性
  • MyDropDownList<状态>会有一个SelectedState属性

使用LINQ,我可以在分组期间创建匿名类型,如下所示:

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

这将生成包含Gender属性和List< User>的生成的匿名类型的列表。可以通过IntelliSense检测到。问题是,我能以某种方式使用泛型类中的属性吗?

编辑:我现在意识到我实际上是在C#3.0中要求“method_missing”,这可能是不可能的。不过,我愿意接受建议。

2 个答案:

答案 0 :(得分:1)

不,你不能这样做。泛型类型背后的整个想法是它们同样适用于可以在泛型参数中指定的所有类型。如果允许每个专业化声明不同名称的成员,情况就不会如此。

答案 1 :(得分:1)

我认为你不能这样做。即使是远程工作机会的唯一方法是创建某种创建类型并返回它的工厂方法。基本上你的泛型类型成为基类,IL是动态编写的,创建一个继承自泛型但具有新属性的具体类。当然返回的对象实际上是匿名的,你只能访问它通过反射,因为你没有实际强制转换的类型:

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

然后使用它需要

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

这不是一个简单的T SelectedItem属性的升级。


从简短的说来看,当c#4.0为我们带来动态类型时,这种类型的东西会更容易。通过实现IDynamicObject接口,可以捕获对未定义属性的所有调用并处理它们,以便您可以使用如下逻辑:

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

我一直关注this article并且还没有触及动态,但它看起来确实像你想要的那样。我仍然不会这样做 - 你不会得到Intellisense,它似乎是一个脆弱而复杂的定义功能的方法。