简体   繁体   中英

C# get custom attribute extension method

can someone help me to create an extension method for custom attributes for newtonsoft.json and mongodb?

Let's say I've following class:

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

How to create an extension method to get the following:

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

or directly with the class itself:

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

I've tried stuff like this:

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

But is there a way to do it without parameter?

THX in advance

You can't do that directly on the property; you would need to apply the extension method to the class and use an expression to select the property:

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

Usage:

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

You may also want to update the code to guard against other members being selected (eg a method), which could be done like this:

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

You can get an attribute and it's value using reflection:

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

You use it like this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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