简体   繁体   English

获取PropertyInfo的默认值而不实例化对象?

[英]Get the default value of a PropertyInfo without instantiating the object?

I got this code that works (simplified) : 我得到了这个有效的代码(简化):

Assembly lib = Assembly.LoadFile("C:\\mydll.dll");
var libType = lib.GetTypes();
Type mvType = libType[0];
PropertyInfo WidthProperty = mvType.GetProperty("Width");

But then, I'd like to access to the default value with a code like 但是,我想用类似的代码访问默认值

var WidthPropertyValue = WidthProperty.GetValue(???, null);

The thing is that we CAN'T instantiate the object with Activator.CreateInstance cause the constructor need that the whole huge project is loaded to work... anyway, that's not the point about working around that problem. 问题是我们无法使用Activator.CreateInstance实例化对象,导致构造函数需要加载整个巨大的项目才能工作......无论如何,这不是解决该问题的重点。 The thing is that, is it possible to access to the default way with this strategy ? 问题是,是否可以使用此策略访问默认方式? Is it possible with another way ? 有可能用另一种方式吗? completely impossible ? 完全不可能?

You need to clarify what you mean by "the default value"... Is it the default value of the property type? 您需要通过“默认值”来澄清您的意思...它是属性类型的默认值吗? In that case, it's null for a reference type, and for a value type it's an instance created with the default constructor: 在这种情况下,对于引用类型它是null,对于值类型,它是使用默认构造函数创建的实例:

static object GetDefaultValue(PropertyInfo prop)
{
    if (prop.PropertyType.IsValueType)
        return Activator.CreateInstance(prop.PropertyType);
    return null;
}

If you mean "the value declared with DefaultValueAttribute ", you can retrieve it like this: 如果您的意思是“使用DefaultValueAttribute声明的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;
}

If you want the value assigned to the property in the constructor, there is no way to get it without creating an instance of the class (well, you could decompile the code, but it's not exactly easy...) 如果你想在构造函数中分配给属性的值,没有创建类的实例就没有办法得到它(好吧,你可以反编译代码,但这并不容易......)

If the assembly code is accessible I would recommend defining default values with an Attribute . 如果可以访问汇编代码,我建议使用Attribute定义默认值。

Otherwise I don't think its possible. 否则我认为不可能。 Property default values are not part of an assembly's metadata (default value concept does not exist as such, that is why DefaultValueAttribute exists) so I'm not sure you can figure it out short of creating an instance of the object. 属性默认值不是程序集元数据的一部分(默认值概念不存在,这就是DefaultValueAttribute存在的原因)所以我不确定你能否解决它创建对象的实例的问题。 It could be anything: default value of the backing field, some value set in the constructor, it could be based on some environment condition, etc. 它可以是任何东西:支持字段的默认值,构造函数中设置的某个值,它可以基于某些环境条件等。

UPDATE : I've seen a few answers/comments pointing to creating the default type of the property's type. 更新 :我看到一些答案/评论指向创建属性类型的默认类型。 Property default values are implementation specific, not type specific. 属性默认值是特定于实现的,而不是特定于类型。 They might coincide in many cases but it doesn't have to be so. 在许多情况下,它们可能会重合但不一定如此。

If the value is being set in the constructor and you can't actually call the constructor, it's not easy to extract the value. 如果在构造函数中设置了值,并且实际上无法调用构造函数,则提取值并不容易。 This is because the value is actually embedded in the code of the constructor. 这是因为该值实际上嵌入在构造函数的代码中。

If you're really brave and have a lot of time on your hands, you can try inspecting the IL directly using a tool like Cecil . 如果你真的很勇敢并且有很多时间在手上,你可以尝试使用像塞西尔这样的工具直接检查IL。 If the property is a simple type (int, double, string, etc.) then you can do the following: 如果属性是简单类型(int,double,string等),那么您可以执行以下操作:

If being set via a field in the constructor: 如果通过构造函数中的字段设置:

  1. Determine the field name for the property. 确定属性的字段名称。 You can either guess a name based on coding conventions (not pretty, but it might get the job done depending on the intention of your tool) or you can do further inspection of the property getter to see what fields it uses. 您可以根据编码约定来猜测名称(不是很漂亮,但可能会根据工具的意图完成工作),或者您可以进一步检查属性getter以查看它使用的字段。 Even this could be tricky if the property does more than just return the value. 如果属性不仅仅返回值,那么即使这可能也很棘手。

  2. Inspect the constructor code and look for references to the field. 检查构造函数代码并查找对该字段的引用。 This could be complicated if the constructor calls other methods that set default values. 如果构造函数调用其他设置默认值的方法,这可能会很复杂。

  3. Once you find the Stfld for the field of interest, look immediately above it for the constant value (Ldc_I4, Ldc_R4, Ldc_R8 or Ldstr.) 一旦找到感兴趣的字段的Stfld,请在其上方查看常量值(Ldc_I4,Ldc_R4,Ldc_R8或Ldstr。)

If being set via a property in the constructor: 如果通过构造函数中的属性设置:

  1. Determine the property setter and look for calls to the setter in the code. 确定属性设置器并在代码中查找对setter的调用。

  2. As with the field case, inspect immediately before the call to look at the loaded constant value. 与现场情况一样,在调用之前立即检查以查看加载的常量值。

If you really want to try this, I recommend creating various types of constructors and inspecting the code in ildasm first, to get an idea for how the code looks when compiled. 如果你真的想尝试这个,我建议首先创建各种类型的构造函数并检查ildasm中的代码,以了解代码在编译时的外观。 Automatically determining the default value will be extremely difficult to do in the general case, but quite achievable for 'common' cases, which might suffice for your purposes. 在一般情况下,自动确定默认值将非常困难,但对于“常见”情况可以实现,这可能足以满足您的需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM