获取给定名称的属性的默认值

发布于 2024-11-08 17:13:13 字数 437 浏览 0 评论 0原文

我有一个财产(示例如下)。

 [DefaultValue(false)]
 public bool MyProperty {
    get {
       return myVal;
    }
    set {
       myVal=value;
    }
 }

我使用它的情况是确保如果未设置默认值,它在 PropertyGrid 中显示为粗体

我发现非常烦人的是,在我的构造函数中,我必须设置属性的初始值,并希望它们匹配。

是否可以让我的构造函数“发现”给定属性的默认值,并进行相应的设置?像这样的东西:

myctor()
{
   myVal = GetDefaultValueProperty<bool>("MyProperty");
}

I have a property, (example shown below).

 [DefaultValue(false)]
 public bool MyProperty {
    get {
       return myVal;
    }
    set {
       myVal=value;
    }
 }

The situation I'm using this is to make sure it shows up as bold in the a PropertyGrid if the default value is not set.

I find it incredibly annoying that in my constructor, I have to set the initial value of my property, and hope that they match up.

Is it possible to have my constructor "discover" the default value of a given property, and set it accordingly? Something like:

myctor()
{
   myVal = GetDefaultValueProperty<bool>("MyProperty");
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你的背包 2024-11-15 17:13:13

您可以使用以下代码来获取您想要的元数据。

public static T GetDefaultValue<T>(string propertyName)
{
    var property = typeof(MyClass).GetProperty(propertyName);

    var attribute = property
        .GetCustomAttribute(typeof(DefaultValueAttribute)) 
            as DefaultValueAttribute;

    if(attribute != null)
    {
        return (T)attribute.Value;
    }
}

如果您想做一些真正的事情,您可以使用 Lambda 表达式来实现:

public static T GetDefaultValue<T>(
    Expression<Func<T, MyClass>> propertySelector)
{
    MemberExpression memberExpression = null;

    switch (expression.Body.NodeType)
    {
        case ExpressionType.MemberAccess:
            // This is the default case where the 
            // expression is simply member access.
            memberExpression 
                = expression.Body as MemberExpression;
            break;

        case ExpressionType.Convert:
            // This case deals with conversions that 
            // may have occured due to typing.
            UnaryExpression unaryExpression 
                = expression.Body as UnaryExpression;

            if (unaryExpression != null)
            {
                memberExpression 
                    = unaryExpression.Operand as MemberExpression;
            }
            break;
    }


    MemberInfo member = memberExpression.Member;

    // Check for field and property types. 
    // All other types are not supported by attribute model.
    switch (member.MemberType)
    {
        case MemberTypes.Property:
            break;
        default:
            throw new Exception("Member is not property");
    }

    var property = (PropertyInfo)member;

    var attribute = property
        .GetCustomAttribute(typeof(DefaultValueAttribute)) 
            as DefaultValueAttribute;

    if(attribute != null)
    {
        return (T)attribute.Value;
    }
}

用法如下:

myctor()
{
   myVal = GetDefaultValue(x => x.MyProperty);
}

You can use the following code to get the metadata you're after.

public static T GetDefaultValue<T>(string propertyName)
{
    var property = typeof(MyClass).GetProperty(propertyName);

    var attribute = property
        .GetCustomAttribute(typeof(DefaultValueAttribute)) 
            as DefaultValueAttribute;

    if(attribute != null)
    {
        return (T)attribute.Value;
    }
}

If you want to do something really cool, you can do this with a Lambda expression:

public static T GetDefaultValue<T>(
    Expression<Func<T, MyClass>> propertySelector)
{
    MemberExpression memberExpression = null;

    switch (expression.Body.NodeType)
    {
        case ExpressionType.MemberAccess:
            // This is the default case where the 
            // expression is simply member access.
            memberExpression 
                = expression.Body as MemberExpression;
            break;

        case ExpressionType.Convert:
            // This case deals with conversions that 
            // may have occured due to typing.
            UnaryExpression unaryExpression 
                = expression.Body as UnaryExpression;

            if (unaryExpression != null)
            {
                memberExpression 
                    = unaryExpression.Operand as MemberExpression;
            }
            break;
    }


    MemberInfo member = memberExpression.Member;

    // Check for field and property types. 
    // All other types are not supported by attribute model.
    switch (member.MemberType)
    {
        case MemberTypes.Property:
            break;
        default:
            throw new Exception("Member is not property");
    }

    var property = (PropertyInfo)member;

    var attribute = property
        .GetCustomAttribute(typeof(DefaultValueAttribute)) 
            as DefaultValueAttribute;

    if(attribute != null)
    {
        return (T)attribute.Value;
    }
}

Usage is then:

myctor()
{
   myVal = GetDefaultValue(x => x.MyProperty);
}
花开柳相依 2024-11-15 17:13:13

您可以调用 GetProperty 方法来查找属性,然后调用 GetCustomAttributes(typeof(DefaultValueAttribute) (并转换其结果)来获取应用的属性。

You can call the GetProperty method to find the property, then call GetCustomAttributes(typeof(DefaultValueAttribute) (and cast its result) to get the attribute applied.

月棠 2024-11-15 17:13:13

这是基于 Paul Turner 的答案的通用扩展方法。它适用于任何类别的任何成员。

public static bool TryGetDefaultValue<TSource, TResult>(this TSource _, Expression<Func<TSource, TResult>> expression, out TResult result)
{
    if (((MemberExpression)expression.Body).Member.GetCustomAttribute(typeof(DefaultValueAttribute)) is DefaultValueAttribute attribute)
    {
        result = (TResult)attribute.Value;
        return true;
    }

    result = default;
    return false;
}

或者,如果未找到该属性,您可以接受返回默认值,请使用此:

public static TResult GetDefaultValue<TSource, TResult>(this TSource _, Expression<Func<TSource, TResult>> expression)
{
    if (((MemberExpression)expression.Body).Member.GetCustomAttribute(typeof(DefaultValueAttribute)) is DefaultValueAttribute attribute)
    {
        return (TResult)attribute.Value;
    }

    return default;
}

您还可以修改它以在未找到该属性时引发异常。

Here's a generic extension method based on Paul Turner's answer. It will work for any member of any class.

public static bool TryGetDefaultValue<TSource, TResult>(this TSource _, Expression<Func<TSource, TResult>> expression, out TResult result)
{
    if (((MemberExpression)expression.Body).Member.GetCustomAttribute(typeof(DefaultValueAttribute)) is DefaultValueAttribute attribute)
    {
        result = (TResult)attribute.Value;
        return true;
    }

    result = default;
    return false;
}

Alternatively, you're OK with the default value being returned if the attribute was not found, use this:

public static TResult GetDefaultValue<TSource, TResult>(this TSource _, Expression<Func<TSource, TResult>> expression)
{
    if (((MemberExpression)expression.Body).Member.GetCustomAttribute(typeof(DefaultValueAttribute)) is DefaultValueAttribute attribute)
    {
        return (TResult)attribute.Value;
    }

    return default;
}

You could also modify it to throw an exception if the attribute wasn't found.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文