C# 在不实例化对象的情况下获取PropertyInfo的默认值?

C# 在不实例化对象的情况下获取PropertyInfo的默认值?,c#,reflection,C#,Reflection,我得到了这个代码,它可以工作(简化): 但是,我想使用如下代码访问默认值 var WidthPropertyValue = WidthProperty.GetValue(???, null); 问题是我们不能用Activator.CreateInstance实例化对象,因为构造函数需要加载整个大型项目才能工作。。。无论如何,这不是解决这个问题的重点。 问题是,是否有可能使用此策略访问默认方式? 有没有别的办法? 完全不可能?如果可以访问汇编代码,我建议使用属性定义默认值 否则我认为这是不可能的

我得到了这个代码,它可以工作(简化):

但是,我想使用如下代码访问默认值

var WidthPropertyValue = WidthProperty.GetValue(???, null);
问题是我们不能用Activator.CreateInstance实例化对象,因为构造函数需要加载整个大型项目才能工作。。。无论如何,这不是解决这个问题的重点。 问题是,是否有可能使用此策略访问默认方式? 有没有别的办法?
完全不可能?

如果可以访问汇编代码,我建议使用
属性定义默认值

否则我认为这是不可能的。属性默认值不是程序集元数据的一部分(默认值概念本身并不存在,这就是为什么
DefaultValueAttribute
存在的原因),因此我不确定您能否在创建对象实例之前找到它。它可以是任何内容:支持字段的默认值、构造函数中设置的某些值、它可以基于某些环境条件,等等


更新:我看到一些答案/注释指向创建属性类型的默认类型。属性默认值是特定于实现的,而不是特定于类型的。在许多情况下,它们可能是一致的,但不一定如此。

您需要澄清“默认值”的含义。。。它是属性类型的默认值吗?在这种情况下,引用类型为null,值类型为使用默认构造函数创建的实例:

static object GetDefaultValue(PropertyInfo prop)
{
    if (prop.PropertyType.IsValueType)
        return Activator.CreateInstance(prop.PropertyType);
    return null;
}
如果您的意思是“使用
DefaultValueAttribute
声明的值”,则可以如下方式检索该值:

static object GetDefaultValue(PropertyInfo prop)
{
    var attributes = prop.GetCustomAttributes(typeof(DefaultValueAttribute), true);
    if (attributes.Length > 0)
    {
        var defaultAttr = (DefaultValueAttribute)attributes[0];
        return defaultAttr.Value;
    }

    // Attribute not found, fall back to default value for the type
    if (prop.PropertyType.IsValueType)
        return Activator.CreateInstance(prop.PropertyType);
    return null;
}

如果您希望在构造函数中为属性分配值,则在不创建类实例的情况下无法获取该值(当然,您可以反编译代码,但这并不容易…)

如果在构造函数中设置值,并且您无法实际调用构造函数,则提取该值并不容易。这是因为该值实际上嵌入在构造函数的代码中

如果你真的很勇敢并且有很多时间,你可以试着直接使用一个工具来检查IL,比如。如果属性是简单类型(int、double、string等),则可以执行以下操作:

如果通过构造函数中的字段设置:

static object GetDefaultValue(PropertyInfo prop)
{
    if (prop.PropertyType.IsValueType)
        return Activator.CreateInstance(prop.PropertyType);
    return null;
}
  • 确定属性的字段名。您可以根据编码约定猜测一个名称(不太漂亮,但可能会根据工具的意图完成任务),也可以进一步检查属性getter以查看它使用的字段。如果属性不只是返回值,那么即使这样也可能很棘手

  • 检查构造函数代码并查找对该字段的引用。如果构造函数调用其他设置默认值的方法,这可能会很复杂

  • 找到感兴趣字段的Stfld后,立即在其上方查找常量值(Ldc_I4、Ldc_R4、Ldc_R8或Ldstr)

  • 如果通过构造函数中的属性设置:

    static object GetDefaultValue(PropertyInfo prop)
    {
        if (prop.PropertyType.IsValueType)
            return Activator.CreateInstance(prop.PropertyType);
        return null;
    }
    
  • 确定属性setter并在代码中查找对setter的调用

  • 与字段情况一样,在调用之前立即检查以查看加载的常量值


  • 如果您真的想尝试这一点,我建议您首先创建各种类型的构造函数并检查ildasm中的代码,以了解编译时代码的外观。自动确定默认值在一般情况下非常困难,但在“普通”情况下是可以实现的,这可能足以满足您的目的。

    您到底在说什么“默认值”?设计者会通过属性或构造函数中指定的初始值来遵循的一种方法?举个例子会很有帮助。我会说构造函数的初始值,但我可以访问所有这些默认值,而无需实例化对象?!?如果值是在构造函数中赋值的,那么唯一知道它的就是构造函数本身。因此,除了创建实例之外,我看不到其他方法。@GuillaumeSlashy:如果值是由代码指定的,那么在不执行该代码的情况下,如何计算它呢?也许该代码需要
    日期时间。现在
    ,或者进行web服务调用…您不能使用类似于此处介绍的解决方案吗?是的,这是我问题的重点,但我觉得这是不可能的,我希望有一个神奇的解决办法,因为有时会发生在这里:)关于编辑源代码,我们不能这样做,但我会记住这一点,为未来!我的财产信息的类型是双重的,但考虑到我们想要做什么,你所说的显然是不可能的:)但我一定会看一看