对象属性的自定义扩展方法 return DefaultValue

Custom Extension Method on object properties to return DefaultValue

我想创建一个自定义扩展,它可以处理对象 T 的属性,而不管 属性 的类型。我需要扩展来获取 DefaultValue 属性的值。

看着下面的class,我希望能够做这样的事情:

Employee employee = new Employee();
string defaultNationality = employee.employeeNationality.GetDefaultValue();

其中 Employee 定义为

public class Employee
{
    [Browsable(false)]
    public int employeeKey { get; set; }

    [DisplayName("Name")]
    [Category("Design")]
    [Description("The name of the employee.")]
    public string employeeName { get; set; }

    [DisplayName("Active")]
    [Category("Settings")]
    [Description("Indicates whether the employee is in active service.")]
    [DefaultValue(true)]
    public bool employeeIsActive { get; set; }

    [DisplayName("Nationality")]
    [Category("Settings")]
    [Description("The nationality of the employee.")]
    [DefaultValue("Dutch")]
    public string employeeNationality { get; set; }
}

您需要使用GetCustomAttribute方法来获取所需的属性值。 例如, 您可以将所需的扩展方法定义为

using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

public static class Extensions
{
    public static T GetDefaultValue<S,T>(this S source,Expression<Func<S,T>> expression)
    {
        var body = expression.Body as MemberExpression;
        if(body.Member.GetCustomAttributes<DefaultValueAttribute>().Any())
        {
             return (T)body.Member.GetCustomAttribute<DefaultValueAttribute>().Value;
        }
        return default;
    }
}

如果找不到所需的属性(在本例中为 DefaultValueAttribute),您可以 return 类型的默认值(或抛出异常,具体取决于您的用例)。

用法为

string defaultNationality = employee.GetDefaultValue(x => x.employeeNationality);   

您可以使用这样的扩展方法:

using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
public static class ObjectExtensions
{
    public static K GetDefaultValue<T, K>(this T obj, Expression<Func<T, K>> exp)
    {
        var info = ((MemberExpression)exp.Body).Member;
        return (K)(TypeDescriptor.GetProperties(info.DeclaringType)[info.Name]
            .Attributes.OfType<DefaultValueAttribute>()
            .FirstOrDefault()?.Value ?? default(K));
    }
}

并像这样使用它:

var deualtValue = someObject.GetDefaultValue(x=>x.SomeProperty);

备注

  • 该方法尝试根据DefaultValue属性获取属性的默认值,如果属性没有这样的属性,它returns 属性 类型的默认值,例如对于整数 属性,如果找不到 DefaultValue 属性,则 returns 0。

  • 为了获取属性和元数据,我通常使用TypeDescriptor因为它更灵活,但是使用反射也完全有效。