[英]C# Pass Generics At Runtime
我有一个像下面这样的方法:
public IEnumerable<T> GetControls<T>()
: where T : ControlBase
{
// removed.
}
然后我创建了一个类:
public class HandleBase<TOwner> : ControlBase
: TOwner
{
// Removed
}
我想能打电话
GetControls<HandleBase<this.GetType()>>;
它将使用THIS类的类型传递给HandleBase。 这基本上会使所有拥有此类型所有者的HandleBase。
我怎样才能做到这一点?
编辑:
我正在使用.NET 2.0,因此大于2.0的解决方案将无效。
这个想法是让ControlBase拥有一个其他ControlBase的集合,用于“孩子们”。 然后可以使用GetControls<T>()
根据类型查询它们。 例如,这将允许我为Shape获取所有HandleBase。 然后我可以采取所有这些并设置Visible = false或用它们做其他事情。 因此,我可以为一个集合操纵特定类型的孩子。
HandleBase<TOwner>
需要TOwner,因为它引用了“拥有类型”。 因此,您只能添加任何将HandleBase扩展到Shape的内容。 说得通?
感谢您的帮助!
您可以通过在编译时指定类型或使用反射来执行此操作。
你可以用这样的反射做到这一点:
typeof(SomeClass).GetMethod("GetControls")
.MakeGenericMethod(typeof(HandleBase<>).MakeGenericType(GetType()))
.Invoke(someObject, null);
注意它会返回一个object
; 你将无法将其IEnumerable<T>
为IEnumerable<T>
(除非你知道T
在编译时是什么,在这种情况下没有意义)。 你可以把它投射到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> {
}
可能没有办法做你要求的。 扩展你的例子:
X x = GetControls<HandleBase<this.GetType()>>;
X型应该在这里? 但是,根据其他背景信息,您似乎需要获取给定类型的所有控件的列表。 你可以这样做,例如:
public IEnumerable<ControlBase> GetControls(Type type) {
//your logic here
}
根据您的其他用途和目标,您可能还希望返回非通用的IEnumerable。
由于GetControls()返回枚举,您可能会找到一种方法来使用.OfType <T>过滤生成的枚举,类似于
List<T2> list = controlList.GetControls<T>().OfType<T2>().ToList();
你需要一个通用的约束
where T2 : T
这特定于我对此的实现,但我能够通过先创建一个非通用的HandleBase
然后再创建一个通用的HandleBase<TOwner>
来解决这个问题,因为唯一使用TOwner的地方是属性所有者。
然后当我可以调用GetControls<HandleBase>
并获得所有HandleBase而不管所有者。
谢谢大家的回答!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.