如何使用反射获取声明的类型

How to get declared types using reflection

我正在尝试使用反射获取声明的类型。它对不可为 null 的类型工作正常,但对可为 null 的类型无效。

class Product
{
    public decimal Price { get; set; }
    public decimal? OfferPrice { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        Type t = typeof(Product);
        var properties = t.GetProperties();
        PropertyInfo price_pInfo = t.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.Name == "Price").FirstOrDefault();
        Console.WriteLine("Member 'Price' was defined as " + price_pInfo.PropertyType);


        PropertyInfo offerprice_pinfo = t.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.Name == "OfferPrice").FirstOrDefault();
        Console.WriteLine("Member 'OfferPrice' was defined as " + offerprice_pinfo.PropertyType);

    }

输出:

Member 'Price' was defined as System.Decimal
Member 'OfferPrice' was defined as System.Nullable`1[System.Decimal] //I am expecting to get Nullable<System.Decimal>

decimal?Nullable<decimal> 的语法糖,是 泛型 。运行时将 Nullable<decimal> 表示为 "System.Nullable`1[decimal]"。来自 official docs:

The name of a generic type ends with a backtick (`) followed by digits representing the number of generic type arguments. The purpose of this name mangling is to allow compilers to support generic types with the same name but with different numbers of type parameters, occurring in the same scope.

没有内置方法来检索泛型类型的代码内表示,您必须手动编辑类型名称。由于您只关心 Nullable<T>:

public static string GetNullableTypeCodeRepresentation(string typeName)
{
    return Regex.Replace(typeName, @"\.Nullable`1\[(.*?)\]", ".Nullable<>");
}

然后:

static void Main(string[] args)
{
    Type t = typeof(Product);
    var properties = t.GetProperties();
    PropertyInfo price_pInfo = t.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.Name == "Price").FirstOrDefault();
    Console.WriteLine("Member 'Price' was defined as " + price_pInfo.PropertyType);

    PropertyInfo offerprice_pinfo = t.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.Name == "OfferPrice").FirstOrDefault();
    Console.WriteLine("Member 'OfferPrice' was defined as " + GetNullableTypeCodeRepresentation(offerprice_pinfo.PropertyType.ToString()));
}

打印:

Member 'Price' was defined as System.Decimal
Member 'OfferPrice' was defined as System.Nullable<System.Decimal>