2010-04-09 46 views
9

我有类似下面的方法:C#通行证泛型在运行时

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 for“children”的集合。然后他们可以根据他们的类型与GetControls<T>()查询。例如,这可以让我得到一个Shape的所有HandleBase。然后,我可以采取所有这些,并设置Visible = false或与他们一起做其他事情。因此,我可以操纵特定类型的儿童进行收藏。

HandleBase<TOwner>需要陶纳,因为它具有与“拥有类型”的引用。所以你只能添加任何将HandleBase扩展到Shape的东西。合理?

感谢您的帮助!

+2

@TheCloudlessSky,为什么调用'this.GetType()'?如果你正在调用'GetControls >();'从一个基于实例的类[如'this'指示],为什么不简单地使用实现类的声明类型名?如果这是一个基类,则有将子类的类型暴露给基类的方法。 – 2010-04-09 14:46:33

+0

请参阅上面的修改。 – TheCloudlessSky 2010-04-09 16:07:41

回答

0

这是具体到我实现这一点,但我可以通过创建一个非通用HandleBase,然后再一个通用HandleBase<TOwner>,因为唯一的地方来解决这个TOWNER正在使用的是业主。

然后,当我可以调用GetControls<HandleBase>并获得所有的HandleBase而不管所有者。

谢谢你的回答!

2

你不能。泛型是一个编译时功能。您需要将该类型作为非泛型参数包含在该方法中,并将其传递给该方法。

+1

你可以使用反射来做到这一点。但是对于问题中所描述的内容来说,这看起来真是太过于夸张了。我同意将类型引用传递给函数。 – 2010-04-09 14:31:44

+0

System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly(); 类型t = a.GetType(“SeaSharpWinApp8.Program”); MethodInfo mi = t.GetMethod(“f”,BindingFlags.Static | BindingFlags.NonPublic); MethodInfo miGeneric = mi.MakeGenericMethod(new Type [] {typeof(string)}); miGeneric.Invoke(null,new object [] {“works”}); – 2010-04-09 14:47:44

+0

这是MakeGenericMethod调用,可以让你做到这一点。您必须先获取MethodInfo,然后再获取您想要使用的特定类型。如果它是一个泛型类型,那么你在类型级别进行MakeGeneric *调用。 – 2010-04-09 14:48:42

13

您可以通过在编译时指定类型或使用反射来执行此操作。

你可以用反射像这样做:

typeof(SomeClass).GetMethod("GetControls") 
    .MakeGenericMethod(typeof(HandleBase<>).MakeGenericType(GetType())) 
    .Invoke(someObject, null); 

注意,它会返回一个object;你将无法将其转换为IEnumerable<T>(除非你知道编译时T是什么,在这种情况下没有意义)。你可以将它投射到IEnumerable

但是,这是一个坏主意。
您可能有更好的解决方案;请提供更多细节。

+0

建议传递类型信息,这可以使用反射吗? **如何?** – serhio 2010-04-09 14:31:03

+3

通过调用'typeof(SomeClass).GetMethod(“GetControls”)可以使用反射。MakeGenericMethod(typeof(HandleBase <>)。MakeGenericType(GetType()))。Invoke(someObject,null )' – SLaks 2010-04-09 14:33:06

+0

为什么这是低调? – SLaks 2010-04-09 14:37:09

1

请注意,类型参数不是变量。因此,您不能使用变量来代替类型参数。

你可以,但是,做到这一点通过反射,或通过使用特殊结构,这是非常有限的,但可以解决您的情况:

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

有可能是没有办法的事,你问什么。扩展你的例子:

X x = GetControls<HandleBase<this.GetType()>>; 

什么样的X应该在这里?但是从其他背景信息看来,您需要获取给定类型的所有控件的列表。你可以在这样的方式,例如做到这一点:

public IEnumerable<ControlBase> GetControls(Type type) { 
//your logic here 
} 

根据您的其他用途,你可能也想返回非通用IEnumerable的目标。

0

的GetControls以来()返回一个枚举,你可能会找到一个方法来生成的枚举与.OfType <牛逼>,像

List<T2> list = controlList.GetControls<T>().OfType<T2>().ToList(); 

过滤您将需要一个通用的限制somehwere沿

线
where T2 : T 
+0

特定于> = 3.0,我忘记提及我正在使用2.0。 – TheCloudlessSky 2010-04-09 16:08:54