【问题标题】:How to obtain value of property from applied attribute?如何从应用属性中获取属性值?
【发布时间】:2019-12-30 21:20:40
【问题描述】:

是否可以从自定义属性中获取类的值(比如说字符串属性)?

例如:

public class test
{
    [EncodeHTML]
    public string body { get; set; }

    public int id { get; set; }
}

我希望自定义属性EncodeHTML能够获取“body”属性的设置值。

我知道这可以通过以下方式实现:

public string body 
{ 
get; 
set {
    value = HttpUtility.HTMLEncode(this);
}

但想知道这是否可以被隔离以在许多类属性中重复使用。

这是自定义属性的一个简单示例:

    [AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
    sealed class EncodeHTMLAttribute : Attribute
    {
        public EncodeHTMLAttribute()
        {

        }
    }

【问题讨论】:

  • 不是真的,属性属于类型,而不是实例。要执行此类操作,您可能需要研究像 Fody 这样的面向方面编程 (AOP),或者自己进行 IL 编织(不推荐)。
  • @RonBeyer 很公平,我希望绕过 [AllowHtml] 或 [ValidateInput(false)] 属性来将模型绑定到控制器。
  • 属性的构造函数在类的任何实例之前运行,因此获取属性的值是没有意义的。话虽如此,一个属性可以包含在运行时触发的处理程序(这就是ActionFilter attribute can access the instance of the controller),但您必须设置一些代码来查找属性并在创建每个实例时调用处理程序。

标签: c# properties


【解决方案1】:

是的

 var attr = typeof(test).GetProperty("body").GetCustomAttribute<EncodeHTMLAttribute>()

你可以访问任何你想要的。

【讨论】:

  • 虽然不适用于我正在寻找的场景,但这对于获取属性本身的值很有用。
  • 我以为您知道如何访问给定实例的属性值。例如,它是 attr.Name。您的属性类没有定义任何自定义属性。您应该使用 [EncodeHtml("somevalue")] 定义一个 value 属性,分配一个值,然后您就可以访问它。
【解决方案2】:

直接回答问题 - 不,属性只是元数据。他们不知道装饰类型的运行时实例甚至存在。

你可以对属性做的最接近的事情是,在运行时,当应用程序启动时,找到所有具有用该属性标记的属性的类型,并将设置器代码重写为你想要的。理论上可以做到,但是很难、很疯狂、很不负责任,完全不推荐。 Refer to this SO question跳进兔子洞。

话虽如此,要解决根本问题,您只需对字符串进行自定义包装即可。

public class HtmlEncodedString
{
    public string Value { get; }

    public HtmlEncodedString(string value) => 
        Value = HttpUtility.HtmlEncode(value);

    public static implicit operator string(HtmlEncodedString htmlEncodedString) => 
        htmlEncodedString.Value;

    public static implicit operator HtmlEncodedString(string value) =>
        new HtmlEncodedString(value);
}

这当然只是一个草图。如果您使用的是 ASP.NET Core,请考虑实现 IHtmlContent。如果你分配了很多这些,也许将其设为值类型会降低 GC 的压力。不用管这些细节,你现在可以通过使用这种类型而不是字符串上的属性来获得可重用性。

public class Test
{
    public HtmlEncodedString Body { get; set; }

    public int Id { get; set; }
}

由于隐式运算符,转换是无缝的:

var test = new Test();
test.Body = "2 < 4";
string s = test.Body;
Console.WriteLine(s);
Console.WriteLine(test.Body);
> 2 &lt; 4
> 2 &lt; 4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多