Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get default value of auto property in C# using reflection?

So I have this class

public class MyClass
{
    public int Id {get; set;} = 5
}

Using reflection how do I get 5 ?

I am trying to avoid creating an instance of MyClass. It seems un-necessary.

Edit: It's called "Auto-Property Initializer" value

from : http://geekswithblogs.net/WinAZ/archive/2015/06/30/whatrsquos-new-in-c-6.0-auto-property-initializers.aspx

like image 645
Bilal Fazlani Avatar asked Jan 10 '18 14:01

Bilal Fazlani


People also ask

How do you give a property a default value?

Right-click the control that you want to change, and then click Properties or press F4. Click the All tab in the property sheet, locate the Default Value property, and then enter your default value. Press CTRL+S to save your changes.

What is the default value of the property?

Definition and Usage Note: The default value is the value specified in the HTML value attribute. The difference between the defaultValue and value property, is that defaultValue contains the default value, while value contains the current value after some changes have been made.

Can we set default value in property C#?

You can assign the default value using the DefaultValueAttribute attribute, as shown below.


3 Answers

That class is actually compiled into this:

public class MyClass
{
    private int MyClass___1<Id> = 5;
    public int Id
    {
        get { return MyClass___1<Id>; }
        set { MyClass___1<Id> = value; }
    }
}

Which in turn is equivalent to this:

public class MyClass
{
    private int MyClass___1<Id>;

    public MyClass()
    {
        MyClass___1<Id> = 5;
    }

    public int Id
    {
        get { return MyClass___1<Id>; }
        set { MyClass___1<Id> = value; }
    }
}

So other than either decompiling the constructor, or constructing an instance of the type, you can't get that value.

If you're the author of the type, the best way to do this would be to apply the [DefaultValue(...)] attribute to the property, which can be read through reflection. Lots of serialization libraries will use this value as well, to avoid serializing a property that has the default value.

Your class would then look like this:

public class MyClass
{
    [DefaultValue(5)]
    public int Id { get; set; } = 5;
}

Having said that, here's a small LINQPad program that demonstrates Mono.Cecil:

void Main()
{
    var assembly = AssemblyDefinition.ReadAssembly(GetType().Assembly.Location);
    var myClassType =
        (from module in assembly.Modules
         from type in module.Types
         where type.Name == "UserQuery"
         from nestedType in type.NestedTypes
         where nestedType.Name == "MyClass"
         select nestedType).FirstOrDefault();

    var ctor =
        (from method in myClassType.Methods
         where method.IsConstructor
         select method).FirstOrDefault();

    foreach (var instruction in ctor.Body.Instructions)
        Console.WriteLine(instruction.ToString());
}

public class MyClass
{
    public int Id { get; set; } = 5;
}

Output:

IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: stfld System.Int32 UserQuery/MyClass::<Id>k__BackingField
IL_0007: ldarg.0
IL_0008: call System.Void System.Object::.ctor()
IL_000d: ret

So it might be feasible in this case, but other types of constants, and so on, like calls to static methods, would not be easy to handle.

In short, create the instance!

like image 102
Lasse V. Karlsen Avatar answered Oct 19 '22 13:10

Lasse V. Karlsen


am trying to avoid creating an instance of MyClass. It seems un-necessary.

Actually it is not. Without the call to the constructor there will be no initialization of the variable Id. But what is much more important is that there will be no memory allocation without the instance so there will be no value at all that you can get.

Using reflection how do I get 5 ?

But if you do create an instance you can get it this way:

Console.WriteLine(typeof(MyClass).GetProperty("Id").GetValue(new MyClass()));
like image 33
Mong Zhu Avatar answered Oct 19 '22 11:10

Mong Zhu


I try the create new Instance with reflection and give a type of instance class in "GetValue", it's worked!

With instance like this:

var myClassType = MyClass.GetType();
var instance = Activator.CreateInstance(myClassType);
var latestInput = MyClass.GetType().GetProperty(input.Name).GetValue(instance);
like image 1
Tonay Avatar answered Oct 19 '22 13:10

Tonay