代码之家  ›  专栏  ›  技术社区  ›  TheCloudlessSky

C在运行时传递泛型

  •  9
  • TheCloudlessSky  · 技术社区  · 14 年前

    我有如下方法:

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

    然后我创建了一个类:

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

    我想打电话给你

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

    它将使用这个类的类型传递到把手。这将在本质上得到所有有这种类型的所有者的把手。

    我怎样才能做到这一点?

    编辑:

    我正在使用.NET2.0,因此大于2.0的解决方案将不起作用。

    其思想是让controlbase为“children”收集其他controlbase。然后可以根据它们的类型使用 GetControls<T>() . 例如,这可以让我得到一个形状的所有把手。然后我可以将所有这些设置为visible=false或对它们执行其他操作。因此,我可以为集合操作特定类型的子级。

    HandleBase<TOwner> 需要城镇居民,因为它引用了“拥有类型”。因此,你只能添加任何延长把手的形状。有道理?

    谢谢你的帮助!

    6 回复  |  直到 14 年前
        1
  •  13
  •   SLaks    14 年前

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

    你可以通过这样的反射来实现:

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

    注意,它将返回 object ;你不能把它投给 IEnumerable<T> (除非你知道 T 是在编译时,在这种情况下没有意义)。你可以把它投给 IEnumerable .

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

        2
  •  2
  •   David M    14 年前

    不能。泛型是编译时特性。您需要将类型作为非泛型参数包含到该方法中,并在其中传递它。

        3
  •  1
  •   Lucero    14 年前

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

    但是,您可以通过反射或使用一个非常有限但可能解决您的情况的特殊构造来实现这一点:

    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> {
    }
    
        4
  •  0
  •   SergGr    14 年前

    可能你要什么就做什么。扩展示例:

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

    X型应该是什么?不过,从其他背景信息来看,似乎需要获取给定类型的所有控件的列表。例如,您可以这样做:

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

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

        5
  •  0
  •   Cylon Cat    14 年前

    由于getControls()返回枚举,您可能会找到一种方法,用.oftype<t>筛选结果枚举,如

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

    你需要一个通用的约束

    where T2 : T
    
        6
  •  0
  •   TheCloudlessSky    14 年前

    这是特定于我的实现,但是我可以通过创建一个非泛型 HandleBase 先是一个泛型 HandleBase<TOwner> 因为唯一一个被使用的地方是房主。

    当我可以打电话的时候 GetControls<HandleBase> 把所有的把手都拿出来,不管主人是谁。

    谢谢大家的回答!