如何从 C# 中的子类型树获取属性的声明类型

How to get declaring type of an atrribute from sub types tree in C#

我花了很多时间寻找如何获取在子类型层次结构中声明属性的类型,但还没有找到任何方法,希望有人知道如何帮助我。

例如我们有一些东西如下:

如果需要,我有一个属性 class 来定义 table 的名称

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class TableBaseAttribute : Attribute
{
    public string Name;
}

那我就可以用它了

[TableBase] // when not assign Name, will get name of the type which declare attribute, in this case is 'Customer'
class Customer
{

}

class CustomerProxy : Customer
{

}

[TableBase(Name = "_USER")]
class User
{

}

class UserRBAC : User
{

}

class UserRBACProxy : UserRBAC
{

}

所以现在,如何解决这个问题

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Table of CustomerProxy is : {0}", GetTableNameFromType(typeof(CustomerProxy)));
        Console.WriteLine("Table of UserProxy is : {0}", GetTableNameFromType(typeof(UserRBACProxy)));
    }

    static string GetTableNameFromType(Type type)
    {
        // what go here to get string of "Customer" for type = CustomerProxy
        //              to get string of "_USER" for type = UserRBACProxy

        TableBaseAttribute tableBaseA = (TableBaseAttribute)typeof(CustomerProxy).GetCustomAttributes(type, true)[0];

        string ret = null;
        if (string.IsNullOrEmpty(tableBaseA.Name))
            ret = ???
        else
            ret = tableBaseA.Name;

        return ret;
    }
}

当没有指定属性覆盖时,您可以使用类型的 Name 属性,这只会给您 class 名称

ret = String.IsNullOrEmpty(tableBaseA.Name) ? type.Name : tableBaseA.Name;

我刚刚意识到以上内容在拉动 TableBase 修饰类型 class 名称的上下文中不起作用,而是采用 current 类型 class名字。在这种情况下,您将需要沿着继承树向上查找基数 class

var baseType = type.BaseType;
while (baseType != null)
{
    var attrs = baseType.GetCustomAttributes(typeof(TableBaseAttribute), false);
    if (attrs.Length > 0) 
    {
        ret = baseType.Name;
        break;
    }
}

我不确定我是否理解正确。您想要声明属性的类型的名称,对吗?如果是这样,这应该有效:

    static string GetTableNameFromType(Type type)
    {
        // what go here to get string of "Customer" for type = CustomerProxy
        //              to get string of "_USER" for type = UserRBACProxy

        TableBaseAttribute tableBaseA = (TableBaseAttribute)type.GetCustomAttributes(typeof(TableBaseAttribute), true)[0];

        string ret = null;
        if (string.IsNullOrEmpty(tableBaseA.Name))
        {
            do
            {
                var attr = type.GetCustomAttributes(typeof(TableBaseAttribute), false);
                if (attr.Length > 0)
                {
                    return type.Name;
                }
                else
                {
                    type = type.BaseType;
                }
            } while (type != typeof(object));
        }
        else
        {
            ret = tableBaseA.Name;
        }

        return ret;
    }