【问题标题】:How to get default value of auto property in C# using reflection?如何使用反射在 C# 中获取自动属性的默认值?
【发布时间】:2018-01-10 14:50:27
【问题描述】:

所以我有这门课

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

使用反射如何获得5

我试图避免创建 MyClass 的实例。好像没必要。

编辑:称为“Auto-Property Initializer”值

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

【问题讨论】:

  • 类不是“初始化”的,除非你创建它们的实例。您可能正在寻找静态类和字段

标签: c# .net reflection


【解决方案1】:

那个类实际上是编译成这样的:

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

所以它可能可行 在这种情况下,但是其他类型的常量等等,比如对静态方法的调用,就不容易处理了。

简而言之,创建实例!

【讨论】:

  • 谢谢。我最终创建了实例。
【解决方案2】:

我试图避免创建 MyClass 的实例。好像没必要。

其实不是。如果不调用构造函数,就不会初始化变量Id。但更重要的是,没有实例就不会分配内存,因此您将无法获得任何价值。

使用反射如何获得 5?

但如果你确实创建了一个实例,你可以通过这种方式获得它:

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

【讨论】:

    【解决方案3】:

    我尝试使用反射创建新实例并在“GetValue”中给出一种实例类,它成功了!

    这样的实例:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-27
      • 1970-01-01
      • 1970-01-01
      • 2011-03-21
      • 1970-01-01
      相关资源
      最近更新 更多