代码之家  ›  专栏  ›  技术社区  ›  Aaron Powell

反射和泛型类型

  •  12
  • Aaron Powell  · 技术社区  · 16 年前

    我正在为一个类构造函数编写一些代码,该类构造函数将遍历类的所有属性,并调用一个通用静态方法,该方法用来自外部API的数据填充我的类。所以我把它作为一个例子:

    public class MyClass{
      public string Property1 { get; set; }
      public int Property2 { get; set; }
      public bool Property3 { get; set; }
    
      public static T DoStuff<T>(string name){
        // get the data for the property from the external API
        // or if there's a problem return 'default(T)'
      }
    }
    

    现在在我的构造器中,我想要这样的东西:

    public MyClass(){
      var properties = this.GetType().GetProperties();
      foreach(PropertyInfo p in properties){
        p.SetValue(this, DoStuff(p.Name), new object[0]);
      }
    }
    

    所以上面的构造函数将抛出一个错误,因为我没有提供泛型类型。

    那么,如何传入属性的类型呢?

    3 回复  |  直到 10 年前
        1
  •  19
  •   radbyx Matt    12 年前

    是否要使用t=每个属性的类型来调用dostuf<t>?在这种情况下,“原样”需要使用反射和makeGenericMethod,即

    var properties = this.GetType().GetProperties();
    foreach (PropertyInfo p in properties)
    {
        object value = typeof(MyClass)
        .GetMethod("DoStuff")
        .MakeGenericMethod(p.PropertyType)
        .Invoke(null, new object[] { p.Name });
        p.SetValue(this, value, null);
    }
    

    不过,这不是很漂亮。事实上,我想知道,仅仅拥有:

    static object DoStuff(string name, Type propertyType);
    ... and then
    object value = DoStuff(p.Name, p.PropertyType);
    

    在这个例子中,泛型给了您什么?请注意,在反射调用期间,值类型仍然会被装箱,甚至装箱。 isn't as bad as you might think .

    最后,在许多场景中,typescriptor.getproperties()比type.getproperties()更合适—允许灵活的对象模型等。

        2
  •  7
  •   nawfal Donny V.    10 年前

    您的构造函数代码是否打算这样读:

    public MyClass(){
      var properties = this.GetType().GetProperties();
      foreach(PropertyInfo p in properties){
        p.SetValue(this, DoStuff(p.Name), new object[0]);
      }
    }
    

    ?注意 DoStuff 而不是 MyClass .

    如果是这样的话,问题是当泛型确实不适用时,您正在尝试使用它们。泛型的要点(好吧,其中之一)是使用编译时类型安全性。在这里,您在编译时不知道类型!您可以通过反射调用该方法(获取打开的窗体,然后调用 MakeGenericMethod )但那很难看。

    道格斯 首先真的需要通用吗?它是从别处使用的吗?的参数 PropertyInfo.SetValue 只是对象,所以即使你 能够 一般地调用方法。

        3
  •  2
  •   Gaspar Nagy    16 年前

    如果您不使用其他地方的dostuff,我还建议编写一个非泛型方法。

    也许您创建了通用方法来使用默认值(T)。要在非泛型方法中替换它,可以对值类型使用Activator.CreateInstance(T),对引用类型使用空值:

    object defaultResult = type.IsValueType ? Activator.CreateInstance(type) : null