在C#中,在属性中声明的方法的目的是什么?如何使用它们?
作为一个例子,看看属性MaxLengthAttribute
:它有很多方法。其中的一种是IsValid()
方法,该方法用于验证应用属性的属性。该验证如何执行?我想针对属性调用了IsValid()
方法,但是我没有找到有关如何调用属性方法的文档。
注意:我有Java背景。在Java中,注释旨在用作元数据,并且声明为use
,因此它们没有方法。
答案 0 :(得分:2)
在几乎所有情况下,答案都是简单的:手动但使用不是您自己的代码。您正在使用的某些框架中的某些代码有意检查这些属性,然后检查它们是否存在:实现它们(最好还进行某种缓存),然后调用该方法。 / p>
属性本身不会做任何事情,但是它们仍然是类型,可以通过反射API来实现。如果您要编写代码来做到这一点:
using System;
[SomeAttribute("boop")]
static class P
{
static void Main()
{
var obj = (SomeAttribute)Attribute.GetCustomAttribute(
typeof(P), typeof(SomeAttribute));
// note the attribute doesn't know the context
// so we need to pass that *in*; an attribute
// doesn't know what it has been attached to
obj?.DoSomething(typeof(P));
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct
| AttributeTargets.Enum)]
class SomeAttribute : Attribute
{
public string Name { get; }
public SomeAttribute(string name)
=> Name = name;
public void DoSomething(Type type)
=> Console.WriteLine($"hey {type.Name} - {Name}");
}
答案 1 :(得分:1)
基本上,属性本身不执行任何操作,必须通过某种框架进行分析。该框架实际执行的操作完全取决于属性创建者。因此,框架可以只检查属性是否存在,但是当然也可以调用其成员。
因此,假设您有以下代码:
[MyAttribute]
class MyClass
{
}
class MyAttribute : Attribute
{
public void DoSomething();
}
现在您有一些代码可以检查属性是否存在,如果存在则调用DoSomething
:
// get types with the attribute
var typesAndAttributes= myAssembly.GetTypes().Select(x => new
{
Type = x,
Attribute = Attribute.GetCustomAttribute(x, typeof(MyAttribute))
});
// now call DoSomething for every attribute
forerach(var e in typesAndAttributes)
{
e.Attribute?.DoSomething();
}
在您的MaxLengthAttribute
示例中,这意味着以下内容。如果您要像这样装饰您的会员:
MaxLengthAttribute(2)
public int[] MyArr = new int[3];
并执行框架为IsValid
调用MyArr
的代码,可能会(不确定,不检查源代码)返回false,因为该值包含3个元素,尽管只有两个被认为是有效的。
答案 2 :(得分:0)
作为一个例子,看看属性MaxLengthAttribute:它有很多方法。其中之一是IsValid()方法,该方法用于验证应用属性的属性。该验证如何执行?我想针对属性调用了IsValid()方法,但是我没有找到有关如何调用属性方法的文档。
这是一个非常简单的示例:
// Start off with an object we're going to validate
public class Foo
{
[MaxLength(5)]
public string Bar { get; set; }
}
var objectToValidate = new Foo() { Bar = "123456" };
// Use reflection to get a list of properties on the object
var properties = objectToValidate.GetType().GetProperties();
foreach (var property in properties)
{
// For each property, get the attributes defined on that property
// which derive from the ValidationAttribute base class
var attributes = property.GetCustomAttributes<ValidationAttribute>();
var propertyValue = property.GetValue(objectToValidate);
foreach (var attribute in attributes)
{
// For each attribute, call its IsValid method, passing in the value
// of the property
bool isValid = attribute.IsValid(propertyValue);
if (!isValid)
{
Console.WriteLine("{0} is invalid", property.Name);
}
}
}
这与Validator.ValidateObject
差不多,除了更多的缓存。
(对于DataAnnotations方法,实际上使用TypeDescriptor基础结构。这使您可以有效地向类及其属性添加属性,而无需直接修改类的源)。