C# 在运行时传递泛型

发布于 2024-08-28 15:33:27 字数 825 浏览 3 评论 0原文

我有一个如下所示的方法:

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() 根据其类型来查询它们。例如,这将使我能够获取形状的所有 HandleBase。然后我可以获取所有这些并设置 Visible=false 或对它们执行其他操作。因此我可以操作集合的特定类型的子项。

HandleBase 需要 TOwner,因为它具有对“所属类型”的引用。因此,您只能添加将 HandleBase 扩展为 Shape 的任何内容。有道理吗?

感谢您的帮助!

I have a method like the following:

public IEnumerable<T> GetControls<T>()
 : where T : ControlBase
{
 // removed.
}

I then created a class:

public class HandleBase<TOwner> : ControlBase
 : TOwner
{
 // Removed
}

I'd like to be able to call

GetControls<HandleBase<this.GetType()>>; 

where it would use the type of THIS class to pass to the HandleBase. This would in essentially get all HandleBase that have an owner of THIS type.

How can I achieve this?

EDIT:

I'm using .NET 2.0 so solutions greater than 2.0 will not work.

The idea is to have ControlBase have a collection of other ControlBase for "children". Then they can be queried based on their type with GetControls<T>(). This would allow me to, for example, get all HandleBase for a Shape. Then I can take all of these and set Visible=false or do something else with them. Thus I can manipulate children of a specific type for a collection.

HandleBase<TOwner> requires the TOwner since it has a reference to the "owning type". So you can only add anything that extends HandleBase to a Shape. Make sense?

Thanks for all the help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

木落 2024-09-04 15:33:27

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

您可以使用反射来完成此操作,如下所示:

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

请注意,它将返回一个对象;您将无法将其转换为 IEnumerable (除非您在编译时知道 T 是什么,在这种情况下没有意义)。您可以将其转换为 IEnumerable

然而,这是一个坏主意。
可能有更好的解决方案适合您;请提供更多详细信息。

You can do this either by specifying a type at compile-time or by using reflection.

You can do it with reflection like this:

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

Note that it would return an object; you would not be able to cast it to IEnumerable<T> (Unless you know what T is at compile-time, in which case there's no point). You would be able to cast it to IEnumerable.

However, this is a bad idea.
There is probably a better solution for you; please provide more detail.

公布 2024-09-04 15:33:27

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

You can't. Generics is a compile-time feature. You would need to include the type as a non-generic parameter to the method, and pass it in there.

允世 2024-09-04 15:33:27

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

但是,您可以通过反射或使用特殊的构造来完成此操作,该构造非常有限,但可以解决您的情况:

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

Note that type parameters are not variables. Therefore, you cannot use a variable in place of a type parameter.

You could, however, do this through reflection, or by using a special construct which is pretty limited but may solve your case:

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> {
}
打小就很酷 2024-09-04 15:33:27

可能没有办法做到你所要求的。扩展你的例子:

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

这里的类型 X 应该是什么?然而,从其他背景信息来看,您似乎需要获取给定类型的所有控件的列表。例如,您可以通过以下方式执行此操作:

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

根据您的其他用法和目标,您可能还想返回非泛型 IEnumerable。

Probably there is no way to do what you ask for. Extending your example:

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

What should the type X be here? However from other background information it seems that you need to get list of all controls of given type. You could do this for example in such way:

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

Depending on your other usages and goals you might also want to return non-generic IEnumerable.

过期情话 2024-09-04 15:33:27

由于 GetControls() 返回一个枚举,您可能会找到一种方法来使用 .OfType过滤生成的枚举,例如

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

您需要一个通用约束,类似于

where T2 : T

Since GetControls() returns an enumeration, you might find a way to filter the resulting enumeration with .OfType<T>, something like

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

You would need a generic constraint somehwere along the lines of

where T2 : T
心凉 2024-09-04 15:33:27

这是特定于我的实现的,但我能够通过首先创建一个非通用 HandleBase 然后创建一个通用 HandleBase 来解决这个问题,因为唯一的地方 TOwner正在使用的是业主。

然后,当我可以调用 GetControls 并获取所有 HandleBase 时,无论所有者是谁。

谢谢大家的解答!

This is specific to my implementation of this but I was able to solve this by creating a non-generic HandleBase first and then a generic HandleBase<TOwner> since the only place TOwner was being used was the property Owner.

Then when I can call GetControls<HandleBase> and get all HandleBase regardless of the Owner.

Thanks all for answers!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文