简体   繁体   中英

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. 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:

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:

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 .

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. 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 . If the property is a simple type (int, double, string, etc.) then you can do the following:

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. 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.)

If being set via a property in the constructor:

  1. Determine the property setter and look for calls to the setter in the code.

  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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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