Bilal Fazlani
Bilal Fazlani

Reputation: 6977

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

Upvotes: 10

Views: 4164

Answers (4)

iKnowNothing
iKnowNothing

Reputation: 979

I had to do this in a generic fashion and thanks to Tonay's answer, I settled on the following:

var myClassType = typeof(T);
var instance = Activator.CreateInstance(myClassType);
var initialValue = typeof(T).GetProperty(itemOfTypeT.PropertyInfo.Name).GetValue(instance,null);

Upvotes: -1

Tonay
Tonay

Reputation: 27

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

Upvotes: 1

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391724

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!

Upvotes: 16

Mong Zhu
Mong Zhu

Reputation: 23732

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()));

Upvotes: 5

Related Questions