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

对泛型类型和隐式转换使用反射

  •  0
  • bmm6o  · 技术社区  · 15 年前

    我正在尝试使用反射来设置某些OpenXML类型的属性(例如,对正)。通过列举所有可能性来赋值是直接的:

    // attr is an XmlAttribute, so .Name and .Value are Strings
    if (attr.Name == "Val")
    {
        if (element is Justification)
        {
            ((Justification)element).Val = (JustificationValues)Enum.Parse(typeof(JustificationValues), attr.Value);
                return;
        }
        else
        {
            // test for dozens of other types, such as TabStop
        }
    }
    

    通过反射很难做到的是: 1)val属性的类型为EnumValue,因此我不知道如何提取要作为第一个参数传递给Enum.Parse的类型。 2)存在从实际枚举类型到枚举值类型的隐式转换,我不知道如何使用反射调用它。

    我希望代码最终看起来像:

    PropertyInfo pInfo = element.GetType().GetProperty(attr.Name);
    Object value = ConvertToPropType(pInfo.PropertyType, attr.Value); /* this 
        would return an instance of EnumValue<JustificationValues> in this case */
    pInfo.SetValue(element, value, null);
    

    如何实现ConvertTopropType?还是有更好的解决方案?

    谢谢

    编辑: 我得到了一个使用Earwicker建议的解决方案,但它依赖于这样一个方便的事实:枚举的类型名可以从节点的类型名派生(“对正”->“对正值”)。不过,在一般情况下,我仍然好奇如何解决这个问题。

    编辑2: 获取通用信息让我走了剩下的路。谢谢。

    3 回复  |  直到 13 年前
        1
  •  4
  •   Daniel Earwicker    15 年前

    如果属性值只是一个字符串,我假设您已经有了某种方法来确定该字符串标识特定枚举中的值。在您的示例中,它是硬编码的,所以我不确定这是您想要的,还是您想要更改的。

    假设您知道它是一个枚举,并且知道哪个枚举,那么您就已经知道了如何获取一个包含右边的装箱值的对象。 enum 键入,就像在代码段中一样。

    现在如果我假设 EnumValue<T> 有一个构造函数 T .

    Type genericType = typeof(EnumValue<>);
    Type concreteType = genericType.MakeGenericType(typeof(JustificationValues));
    

    现在 concreteType 是类型 EnumValue<JustificationValues> .

    从中可以得到一个构造函数,希望它 JustificationValues 参数,以及 Invoke 它。

    更新

    啊,我知道你现在在做什么了。您可以使用XML属性名来选择C属性。您需要能够检测该属性是否属于类型 枚举值<t> 然后找出 T 是。

    PropertyInfo p = // ... get property info
    
    Type t = p.GetType();
    
    if (t.IsGenericType && 
        t.GetGenericTypeDefinition == typeof(EnumValue<>))
    {
        Type e = t.GetGenericArguments()[0]; // get first (and only) type arg
    
        // e is the enum type...
    

    试试看。

        2
  •  1
  •   jbtule    13 年前

    .NET 4.0添加了对执行后期绑定的隐式或显式转换的支持。这在开源框架中得到了简化。 ImpromptuInterface 用它的静态方法调用 InvokeConvert . 在您的理想示例中,它的工作方式如下:

    PropertyInfo pInfo = element.GetType().GetProperty(attr.Name);
    Object value = Impromptu.InvokeConvert(attr.Value, pInfo.PropertyType); 
    pInfo.SetValue(element, value, null);
    
        3
  •  1
  •   Mohamad Elarabi    13 年前

    这可能只适用于基本类型,但对于我所做的来说已经足够好了。

    PropertyInfo pInfo = element.GetType().GetProperty(attr.Name);
    Object value = System.Convert.ChangeType(attr.Value, pInfo.PropertyType);
    pInfo.SetValue(element, value, null);