3

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 ?

Greg
  • 23,155
  • 11
  • 57
  • 79
Guillaume Slashy
  • 3,554
  • 8
  • 43
  • 68
  • 4
    What "default value" are you talking about, exactly? One that a designer would obey, via an attribute, or the initial value assigned in a constructor? An example would really help here. – Jon Skeet Jan 20 '12 at 15:44
  • 1
    I'd say the initial value of the constructor, but I can access to all these default values without instantiating the object ?!? – Guillaume Slashy Jan 20 '12 at 15:47
  • If the value is assigned in the constructor, the only one who knows it is the constructor itself. So i don't see another way than creating an instance. – Tim Schmelter Jan 20 '12 at 15:49
  • @GuillaumeSlashy: If the value is assigned *by code* then how could it possibly be evaluated without executing that code? Perhaps that code takes `DateTime.Now`, or makes a web service call... – Jon Skeet Jan 20 '12 at 15:53
  • 1
    can't u use something like the solution presented here? http://stackoverflow.com/questions/325426/c-sharp-programmatic-equivalent-of-defaulttype – Kralizek Jan 20 '12 at 15:55
  • @Kralizek: that gives you the default value based on the Property type which might have nothing to do with the default value defined in the class. Default values of a property are implementation specific, not type specific, it might be the same in many cases but they don't have to be. – InBetween Jan 20 '12 at 15:59
  • like I said in my question, and @JonSkeet talked about it too, I can't instantiate my object 'cause it calls a lot of services that didn't start, so I can't copy the solution u linked. Anyway, I was quite sure that it was impossible and it sounds to be the case... :/ – Guillaume Slashy Jan 20 '12 at 15:59

3 Answers3

3

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

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
1

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.

InBetween
  • 32,319
  • 3
  • 50
  • 90
  • Yep, that's the point of my question but I got the feeling that it's not possible, I was hoping for a magical solution as it sometimes happen here :) About editing the source, we can't do that but I'll keep that in mind for the future ! – Guillaume Slashy Jan 20 '12 at 15:55
1

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.

Dan Bryant
  • 27,329
  • 4
  • 56
  • 102
  • My PropertyInfo's Type is DOuble but what u're talking about is clearly out of bounds considering what we wanna do :) but I'll surely take a look at it – Guillaume Slashy Jan 20 '12 at 16:02