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

ktca8awb  于 2023-02-20  发布在  .NET
关注(0)|答案(4)|浏览(242)

所以我上了这门课

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

x6492ojm

x6492ojm1#

这个类实际上被编译成了这样:

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

话虽如此,下面是一个演示Mono.Cecil的小LINQPad程序:

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

因此,在这种情况下,它可能是 * 可行的***,但是其他类型的常量等等,比如调用静态方法,就不容易处理了。
简言之,创建示例!

wxclj1h5

wxclj1h52#

我试图避免创建MyClass的示例。这似乎是不必要的。
实际上不是这样的,没有对构造函数的调用,就不会有变量Id的初始化,但更重要的是,没有示例就不会有内存分配,所以你根本就得不到任何值。
利用反射,我怎么得到5?
但是如果你创建了一个示例,你可以这样得到它:

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

azpvetkf3#

我尝试用反射创建新示例,并在“GetValue”中给予示例类的类型,它起作用了!
例如:

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

rjee0c154#

我不得不以一种通用的方式来做这件事,多亏了托内的回答,我决定如下:

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

相关问题