C#获取自定义属性扩展方法

C# get custom attribute extension method

有人可以帮我为 newtonsoft.json 和 mongodb 的自定义属性创建扩展方法吗?

假设我关注了 class:

public class Foo
{
    [BsonElement("MyCustomDbName")]
    [JsonProperty("MyCustomJsonName")]
    public string Name { get; set; }
}

如何创建扩展方法以获取以下内容:

var myFoo = new Foo(){Name=""};
var mongoDbElementName = myFoo.Name.GetMongoDbElementName(); // should return 'MyCustomDbName'
var jsonPropertyName = myFoo.Name.GetJsonPropertyName(); // should return 'MyCustomJsonName'

或直接使用 class 本身:

var mongoDbElementName = Foo.Name.GetMongoDbElementName(); // should return 'MyCustomDbName'
var jsonPropertyName = Foo.Name.GetJsonPropertyName(); // should return 'MyCustomJsonName'

我试过这样的东西:

public static string GetMongoDbElementName(this Type modelType, PropertyInfo property)
{
    return (modelType.GetProperty(nameof(property)) ?? throw new InvalidOperationException()).GetCustomAttribute<BsonElementAttribute>()?.ElementName;
}

但是有没有不用参数的方法呢?

提前致谢

您不能直接在 属性 上这样做;您需要将扩展​​方法应用于 class 并使用表达式 select 属性:

public static string GetMongoDbElementName<T>(
    this T obj,
    Expression<Func<T, object>> propertySelector)
{
    var memberExpression = propertySelector.Body as MemberExpression;
    var memberName = memberExpression?.Member.Name
        ?? throw new InvalidOperationException();

    var bsonAttribute = obj
        .GetType()
        .GetProperty(memberName)
        .GetCustomAttribute<BsonElementAttribute>();

    return bsonAttribute?.ElementName;
}

用法:

var mongoDbElementName = myFoo.GetMongoDbElementName(x => x.Name);

您可能还想更新代码以防止其他成员被 selected(例如方法),可以这样做:

var property = obj
    .GetType()
    .GetProperty(memberName)
    ?? throw new InvalidOperationException($"{memberName} is not a property");
 
var bsonAttribute = property
    .GetCustomAttribute<BsonElementAttribute>();

您可以使用反射获取属性及其值:

public static string GetBsonElementName(this Foo foo)
{
    var bsonElementAttribute =
        typeof(Foo)
        .GetProperty(nameof(Foo.Name))
        .GetCustomAttribute<BsonElementAttribute>();

    return bsonElementAttribute.ElementName;
}

public static string GetJsonPropertyName(this Foo foo)
{
    var jsonPropertyAttribute =
        typeof(Foo)
        .GetProperty(nameof(Foo.Name))
        .GetCustomAttribute<JsonPropertyAttribute>();

    return jsonPropertyAttribute.PropertyName;
}

你这样使用它:

var foo = new Foo();
var bsonElementName = foo.GetBsonElementName();
var jsonPropertyName = foo.GetJsonPropertyName();