自定义 C# 属性

4
在创建自定义属性时,需要创建一个自定义类,并从ValidationAttribute类继承。
public class CustomAttribute: ValidationAttribute
    {
        
       public void Test()
        {
             Console.WriteLine("Hello World");
         }
        public override bool IsValid(object? value)
        {
            //Logic here
            if (condition)
            {
                return true;
            }
            else
                return false;

        }

      }

假设此自定义属性位于模型的某个属性之上。

[Custom]
 public string username { get; set; }

通过将Custom放置在属性上,我正在实例化Custom类。现在我的问题是:
  1. 何时和如何调用IsValid()方法?
  2. 为什么不调用CustomAttribute类中的其他方法?(在这种情况下是Test()方法)
  3. 按照什么标准运行CustomAttribute类中的特定方法?

1
编译器不选择运行什么。应用程序框架 - 在这种情况下,使用反射的是asp.net core。 - Daniel A. White
2个回答

5
您的理解基础不正确。您正在假设这里使用的是“属性”(Attribute),而您需要关注代码行为。 属性是“数据”类,它们不能自行操作。 在执行类和属性的反射时,它们非常有用。 在 DLL 或 EXE 中,您可以看到此数据在运作。 属性有助于“标记”某些东西,我建议学习更多关于反射的知识。
回答您的问题:
1. IsValid 是由框架或您自己调用的,它需要特别提取这些 Attribute 类型并调用 IsValid。 override 关键字是一个很好的提示 - 表示其他内容管理了此行为。
2. 虽然这是可能的,可以通过反射提取所有公共方法并调用它们,但框架并不设计调用自定义公共方法,因为这是不安全、意料之外且一般不被推荐的。
3. 基于框架的基础-如果框架被设计为调用这些方法,那么它们将调用它们,否则它只是不关心您定义的方法。
例如,假设这个傻瓜属性:
    public class MyAttrib : ValidationAttribute
    {
        public MyAttrib()
        {
            Console.WriteLine("Hello from attrib ctor");

        }
        public override bool IsValid(object? value)
        {
            if (value == null) return false;
            if (value != null && value.GetType() != typeof(string))
            {
                return false;
            }
            string? s = value as string;
            return s == "Hello World";
        }
    }

    [MyAttrib]
    public class A
    {

    }

实现框架需要这样做:
            var assm = Assembly.GetExecutingAssembly();

            foreach (var type in assm.GetTypes())
            {
                if (type.IsAssignableFrom(typeof(A)))
                {
                    Console.WriteLine($"Found type {type}");
                    var attributeType = type.GetCustomAttribute<MyAttrib>();
                    var isValid = attributeType.IsValid("Hello World");
                    Console.WriteLine($"Is Valid? {isValid}");
                }
            }

我更专注于反射,因为这是理解属性的关键。


关于像ASP.net这样的框架: 这些框架广泛使用反射来执行许多任务并将行为委托给用户代码。
一个有趣的实验是在你重写的方法上设置断点,并查看它们在代码中被调用的位置。 还要查看不同的属性及其具有的内容,它们的基础是标记特定的数据或行为,例如ValidationAttribute用于对数据执行验证。

祝你好运!


5
通过在我实例化的属性上放置[Custom] ,我正在实例化Custom类。

不是的,那是不正确的。
只有当您使用GetCustomAttributes()方法时,才会创建Attribute实例(并调用它们的构造函数)。这在此处讨论:When is a custom attribute's constructor run? IsValid()方法何时被调用?
只有当某个验证服务(可以是任何内容!)有意选择使用GetCustomAttributes()来查找ValidationAttribute子类,并且它专门使用IsValid()时,才会调用该方法。
为什么CustomAttribute类中的其它方法没有被调用?(在这种情况下为Test()方法)
因为您发布的代码中没有任何尝试通过反射实例化CustomAttribute并在其上调用.Test()的代码。
根据什么基础运行CustomAttribute类中的特定方法?
只有当使用GetCustomAttributes()实例化属性并且 消费者(调用程序)专门编写使用[CustomAttribute]中的方法时,才会运行特定方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接