【问题标题】:Reflection blazor - Get attribute name + value反射 blazor - 获取属性名称 + 值
【发布时间】:2019-11-10 13:29:29
【问题描述】:

在我的父组件上我有这个:

<TestComponent @bind-Value="testString" />

@code {
    [MaxLength(10)]
    private string testString;
}

在我的TestComponent 这个:

<input type="text" @bind="Value" @bind:event="oninput" />

@code {
    [Parameter] public string Value { get; set; }
    [Parameter] public EventCallback<string> ValueChanged { get; set; }

    protected override void OnInitialized() {
        //Get MaxLength here
    }
}

如果ValueMaxLength,我如何检查我的TestComponent 并获得他的价值?

【问题讨论】:

    标签: c# asp.net-core razor blazor


    【解决方案1】:

    我已经需要检查属性以使用DisplayName 渲染标签和Required 向标签添加红色*,我不知道该怎么做,我尝试了normal way 这样做,但现在成功了。

    但后来我记得 Blazor 已经使用 ValidationMessage 执行此操作,因为它从属性中获取属性并对其进行验证......所以我决定检查它的源代码。

    深入挖掘,我找到了this function,它解释了如何做我们需要的事情。

    首先,它有一个 Expression&lt;Func&lt;T&gt;&gt; 参数,在 blazor 中是 ValidationMessageFor 属性,所以我们可以看到这里可能无法使用绑定值或仅传递它就像Foo="@Foo"(如果可能的话,他们可能会这样做),所以我们需要另一个属性来传递该类型

    例如

    <TestComponent @bind-Value="testString" Field=@"(() => testString)" />
    

    现在继续该函数的代码,它将获取表达式的Body 并进行一些检查以获取并确保您正在传递一个属性。
    然后就是这条线。

    fieldName = memberExpression.Member.Name;
    

    如果您查看memberExpression.Member 并调用GetCustomAttributes,您将拥有我们所需要的所有属性的自定义属性。

    所以现在我们只需要循环自定义属性并做任何你想做的事情。

    这里是获取CustomAttributeExpression&lt;Func&lt;T&gt;&gt;中返回的属性的简化版本

    private IEnumerable<CustomAttributeData> GetExpressionCustomAttributes<T>(Expression<Func<T>> accessor)
    {
        var accessorBody = accessor.Body;
    
        // Unwrap casts to object
        if (accessorBody is UnaryExpression unaryExpression
            && unaryExpression.NodeType == ExpressionType.Convert
            && unaryExpression.Type == typeof(object))
        {
            accessorBody = unaryExpression.Operand;
        }
    
        if (!(accessorBody is MemberExpression memberExpression))
        {
            throw new ArgumentException($"The provided expression contains a {accessorBody.GetType().Name} which is not supported. {nameof(FieldIdentifier)} only supports simple member accessors (fields, properties) of an object.");
        }
    
        return memberExpression.Member.GetCustomAttributes();
    }
    

    以你为例,这里是如何解决它

    .剃刀

    <TestComponent @bind-Value="testString" Field="(() => testString)" />
    
    @code {
        [MaxLength(10)]
        private string testString;
    }
    

    TestComponent.razor

    <input type="text" @bind="Value" @bind:event="oninput" />
    
    @code {
        [Parameter] public Expression<Func<string>>Field { get; set; }
        [Parameter] public string Value { get; set; }
        [Parameter] public EventCallback<string> ValueChanged { get; set; }
    
        protected override void OnInitialized()
        {
            base.OnInitialized();
            if (Field != null)
            {
                var attrs = GetExpressionCustomAttributes(Field);
    
                foreach (var attr in attrs)
                {   
                    if(attr is MaxLengthAttribute maxLengthAttribute)
                    {
                        // Do what you want with maxLengthAttribute     
                    }
                }
            }
        }
    
        private IEnumerable<CustomAttributeData> GetExpressionCustomAttributes<T>(Expression<Func<T>> accessor)
        {
            var accessorBody = accessor.Body;
    
            // Unwrap casts to object
            if (accessorBody is UnaryExpression unaryExpression
                && unaryExpression.NodeType == ExpressionType.Convert
                && unaryExpression.Type == typeof(object))
            {
                accessorBody = unaryExpression.Operand;
            }
    
            if (!(accessorBody is MemberExpression memberExpression))
            {
                throw new ArgumentException($"The provided expression contains a {accessorBody.GetType().Name} which is not supported. {nameof(FieldIdentifier)} only supports simple member accessors (fields, properties) of an object.");
            }
    
            return memberExpression.Member.GetCustomAttributes();
        }
    }
    

    如果您只有一个属性,您也可以调用memberExpression.Member.GetCustomAttributes&lt;Attribute&gt;() 来获取该属性类型的列表。

    TL;DR

    向组件添加新属性

    [Parameter] public Expression<Func<T>>Field { get; set; }
    

    使用this gist 辅助函数来获取你想要的属性。

    【讨论】:

      猜你喜欢
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-24
      • 2012-09-01
      • 2010-11-15
      • 2012-05-23
      • 1970-01-01
      相关资源
      最近更新 更多