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
CodePudding user response:
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 (e.g. 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>();
CodePudding user response:
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();