У меня есть метод как следующее:
public IEnumerable<T> GetControls<T>()
: where T : ControlBase
{
// removed.
}
Я затем создал класс:
public class HandleBase<TOwner> : ControlBase
: TOwner
{
// Removed
}
Я хотел бы смочь звонить
GetControls<HandleBase<this.GetType()>>;
где это использовало бы тип ЭТОГО класса, чтобы передать HandleBase. Это было бы в по существу получать все HandleBase, которые имеют владельца ЭТОГО типа.
Как я могу достигнуть этого?
Править:
Я использую.NET 2.0, таким образом, решения, больше, чем 2,0, не будут работать.
Идея состоит в том, чтобы сделать, чтобы ControlBase имел набор другого ControlBase для "детей". Затем они могут быть запрошены на основе их типа с GetControls<T>()
. Это позволило бы мне, например, получило бы весь HandleBase для Формы. Затем я могу взять все их и установить Visible=false или сделать что-то еще с ними. Таким образом я могу управлять детьми определенного типа для набора.
HandleBase<TOwner>
требует TOwner, так как он имеет ссылку на "тип владения". Таким образом, можно только добавить что-либо, что расширяет HandleBase до Формы. Иметь смысл?
Спасибо за всю справку!
Это характерно для моей реализации, но я смог решить эту проблему, создав сначала неуниверсальную HandleBase
, а затем generic HandleBase
, поскольку TOwner использовался только в качестве владельца свойства.
Затем, когда я могу вызвать GetControls
и получить все HandleBase независимо от владельца.
Спасибо всем за ответы!
Вы не можете. Generics - это функция времени компиляции. Вам нужно будет включить тип в метод как неуниверсальный параметр и передать его туда.
Вы можете сделать это, указав тип во время компиляции или используя отражение.
Вы можете сделать это с помощью отражения следующим образом:
typeof(SomeClass).GetMethod("GetControls")
.MakeGenericMethod(typeof(HandleBase<>).MakeGenericType(GetType()))
.Invoke(someObject, null);
Обратите внимание, что он вернет объект
; вы не сможете преобразовать его в IEnumerable
(если вы не знаете, что такое T
во время компиляции, и в этом случае нет смысла). Вы можете преобразовать его в IEnumerable
.
Однако это плохая идея.
Возможно, для вас есть лучшее решение; пожалуйста, предоставьте более подробную информацию.
Вероятно, нет способа сделать то, о чем вы просите. Расширяя ваш пример:
X x = GetControls<HandleBase<this.GetType()>>;
Каким должен быть тип X здесь? Однако из другой справочной информации кажется, что вам нужно получить список всех элементов управления заданного типа. Это можно сделать, например, так:
public IEnumerable<ControlBase> GetControls(Type type) {
//your logic here
}
В зависимости от ваших других применений и целей вы также можете захотеть вернуть негенеративный IEnumerable.
Обратите внимание, что параметры типа не являются переменными. Следовательно, вы не можете использовать переменную вместо параметра типа.
Однако вы можете сделать это с помощью отражения или с помощью специальной конструкции, которая довольно ограничена, но может решить ваш случай:
public class MyClass<TSelf> where TSelf: MyClass<TSelf> {
public IEnumerable<T> GetControls<T>() where T: ControlBase {
// removed.
}
public void MyCall() {
GetControls<HandleBase<TSelf>>();
}
}
public class MyConcreteClass: MyClass<MyConcreteClass> {
}
Поскольку GetControls () возвращает перечисление, вы можете найти способ отфильтровать полученное перечисление с помощью .OfType
List<T2> list = controlList.GetControls<T>().OfType<T2>().ToList();
Вы бы нужно какое-то общее ограничение вроде
where T2 : T