Универсальный ComboBox с автоматически названными свойствами - PullRequest
0 голосов
/ 21 мая 2009

Я пишу оболочку для элемента управления WinForms ComboBox, которая позволит мне заполнить раскрывающийся список списком и имеет свойство Selected, которое возвращает элемент типа T (или ноль, если ничего не выбрано).

Вместо того, чтобы иметь свойство Selected, я бы хотел, чтобы оно называлось на основе общего типа автоматически. Например:

  • MyDropDownList будет иметь свойство SelectedUser
  • MyDropDownList будет иметь свойство SelectedDepartment
  • MyDropDownList будет иметь свойство SelectedState

С помощью LINQ я могу создавать анонимные типы во время группировки, например:

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

В результате будет создан список сгенерированного анонимного типа, содержащий свойство Gender и список , обнаруживаемые IntelliSense. Вопрос в том, могу ли я как-то сделать это со свойствами в общем классе?

РЕДАКТИРОВАТЬ : Теперь я понимаю, что по сути прошу "method_missing" в C # 3.0, что, вероятно, невозможно. Я открыт для предложений.

Ответы [ 2 ]

1 голос
/ 21 мая 2009

Не думаю, что ты сможешь это сделать. Единственный подход, у которого есть хоть какой-то отдаленный шанс на работу, - это создать какой-то фабричный метод, который создал бы тип и возвратил его. По сути, ваш универсальный тип становится базовым классом, а 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 
     }
}

Я следил за этой статьей и сам еще не коснулся динамики, но, похоже, то, что вы хотите, возможно. Я все еще не сделал бы этого - вы не получите Intellisense, и он кажется хрупким и сложным методом определения функциональности.

1 голос
/ 21 мая 2009

Нет, вы не можете этого сделать. Вся идея универсальных типов заключается в том, что они в равной степени применяются ко всем типам, которые могут быть указаны в универсальном параметре. Это было бы не так, если бы каждой специализации разрешалось объявлять членов с разными именами.

...