繁体   English   中英

如何定义一个属性以获取在 c# 中声明它的属性名称?

[英]How to define an attribute to get the property name on which it is declared in c#?

在我的数据库中,所有表都有状态字段,但每个表对该列都有不同的名称。 例如,用户表有 user_status,分支表有 branch_status。 不同表的所有这些列都具有相同的值。 我已经为所有人创建了 POCO 实体,并希望创建一个通用函数来对指定的 POCO 实体类的状态字段执行查询。 所以我想创建一个属性,说明这将是指定实体类的状态字段。

因此,属性将为我提供声明它的属性名称。 该属性将仅在类中的单个属性上声明。 到目前为止,我已经完成了以下操作并且它正在工作,但想知道实现相同目标的有效方法。 下面是我的代码:

自定义属性:

[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public class StatusFieldAttribute : Attribute
{


}

宣言

    public class UserTable
    {

        public int UserId{ get; set; }

         [StatusField]
        public int UserStatus { get; set; }
    }

    public class BranchTable
    {

        public int BranchId{ get; set; }

         [StatusField]
        public int BranchStatus { get; set; }
    }

我想从具有 StatusField 属性的 UserTable 和 BranchTable 中获取属性名称。 我取得了与以下相同的成绩:

        Type type = typeof(UserTable);
        string statusFieldName = type.GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(StatusFieldAttribute))).FirstOrDefault().Name;

上面的代码给出了正确的输出为 UserStatus。 但是有没有一种有效的方法可以使用以下内容来实现相同的目标:

[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public class StatusFieldAttribute : Attribute
{
    public StatusFieldAttribute([CallerMemberName] string propertyName = null)
    {
        StatusFieldName = propertyName;
    }

    public string StatusFieldName { get; }


}

并访问 StatusFieldName 以获取在特定类中声明 StatusField 属性的属性的名称。

一种方法是定义一个标记接口(在 C# 8 之前),并定义一个扩展方法来检索正确的状态字段,如下所示:

interface IStatusFieldMarker
{
}

static class Extensions
{
    public static string GetStatusFieldName(this IStatusFieldMarker t) =>
        t.GetType()
        .GetProperties()
        .Single(p => Attribute.IsDefined(p, typeof(StatusFieldAttributeAttribute)))
        .Name;
    // optional getter/setter
    public static int GetStatus(this IStatusFieldMarker t) =>
        (int)(t.GetType()
        .GetProperty(GetStatusFieldName(t))
        .GetValue(t));
    public static void SetStatus(this IStatusFieldMarker t, int value)
    {
        t.GetType()
        .GetProperty(GetStatusFieldName(t))
        .SetValue(t, value);
    }
}

然后用接口标记 POCO 对象:

class Branch : IStatusFieldMarker
{
    [StatusFieldAttribute]
    public int BranchStatus { get; set; }
}
class User : IStatusFieldMarker
{
    [StatusFieldAttribute]
    public int UserStatus { get; set; }
}

然后可以调用GetStatusFieldName扩展方法来获取字段名称:

Branch b = new Branch() { BranchStatus = 3 };
User u = new User() { UserStatus = 1 };
Console.WriteLine(b.GetStatusFieldName()); // prints BranchStatus
Console.WriteLine(u.GetStatusFieldName()); // prints UserStatus
Console.WriteLine(b.GetStatus()); // prints 3
Console.WriteLine(u.GetStatus()); // prints 1

我只是创建了下面的函数来获取状态名称

    public static string GetStatusField<T>(this T type) where T : Type
    {
         PropertyInfo propertyInfo = type.GetProperties().FirstOrDefault(prop => Attribute.IsDefined(prop, typeof(StatusFieldAttribute)));

        if (propertyInfo == null)
        {
            Log.Error($"StatusFieldAttribute not found in {type.Name} ");
            throw new Exception($"StatusFieldAttribute not found in { type.Name } ");

        }
        else
            return propertyInfo.Name;

    }

并将该函数调用为

Type type = typeof(UserTable);
string statusFieldName = type.GetStatusField();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM