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
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.
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.
You can assign the default value using the DefaultValueAttribute attribute, as shown below.
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!
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()));
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With