如何使用反射在C#中获取auto属性的默认值?

时间:2018-01-10 14:50:28

标签: c# .net reflection

所以我有这个课

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

使用反射如何获得5

我试图避免创建MyClass的实例。这似乎没必要。

编辑:它被称为“自动属性初始化程序”值

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

3 个答案:

答案 0 :(得分:8)

该类实际编译为:

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

反过来又相当于:

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

除了反编译构造函数或构造类型的实例之外,你无法获得该值。

如果您是该类型的作者,最好的方法是将[DefaultValue(...)]属性应用于属性,可以通过反射读取。许多序列化库也将使用此值,以避免序列化具有默认值的属性。

你的课程看起来像这样:

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

话虽如此,这是一个展示LINQPad的小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;
}

输出:

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

所以它可能可行 在这种情况下,但是其他类型的常量,等等,就像对静态方法的调用一样,并不容易处理。 / p>

简而言之,创建实例!

答案 1 :(得分:4)

  

我试图避免创建MyClass的实例。这似乎没必要。

实际上并非如此。如果没有对构造函数的调用,则不会对变量Id进行初始化。但更重要的是,没有实例就没有内存分配,所以你根本就没有价值。

  

使用反射如何获得5?

但是如果你确实创建了一个实例,你就可以这样做:

Console.WriteLine(typeof(MyClass).GetProperty("Id").GetValue(new MyClass()));

答案 2 :(得分:0)

我尝试使用反射创建新的实例,并在“ GetValue”中提供一种实例类,这样就可以了!

具有这样的实例:

var myClassType = MyClass.GetType();
var instance = Activator.CreateInstance(myClassType);
var latestInput = MyClass.GetType().GetProperty(input.Name).GetValue(Instance);