【问题标题】:Real world use of custom .NET attributes自定义 .NET 属性的实际使用
【发布时间】:2010-11-04 14:57:36
【问题描述】:

您在现实世界中将自定义 .NET 属性用于哪些用途?

我已经阅读了几篇关于它们的文章,但我从未使用过自定义属性。

我觉得当它们有用时我可能会忽略它们。

我说的是您创建的属性,而不是已经包含在框架中的属性。

【问题讨论】:

标签: .net attributes custom-attributes class-attributes .net-attributes


【解决方案1】:

我创建了一个脚本引擎,并用 [Command] 属性标记了各种方法。这意味着这些函数会暴露给脚本引擎。

例子:

[Command(HelpText = "Lists active users")]
void ListUsers(void)
{

}

[Command(HelpText = "Terminate a specific user's connection")]
void EndConnection(int userID)
{

}

如使用:

MyScriptEngine>>  Help
Available Commands are:
    ListUsers: Lists active users
    EndConnection {userID}: Terminate a specific user's connection

MyScriptEngine>> EndConnection 3
    User 3 (Michael) has had his connection terminated.

MyScriptEngine>>

【讨论】:

    【解决方案2】:

    我已经使用它们“自定义”属性进行验证(即,使用我自己的“信用卡验证”标记要验证的字段)和我编写的自定义 LinqToLucene 分析器(即指定要在给定字段)。

    例如,验证代码如下所示:

    public class Customer
    {
         [CreditCardValidator]
         string creditCardNumber;
    
         [AddressValidator]
         string addressLineOne
    }
    

    验证上述对象时,由于“自定义”属性,每个字段都使用适当的验证器进行验证。

    在我编写的 LinqToLucene 内容中,自定义属性很好,因为它们允许您在运行时(通过反射)查找特定字段。例如,如果您有一个客户对象,您可能有兴趣获取已标记为“索引我”的所有属性:自定义属性让您可以轻松完成此操作,因为它以一种方式公开有关该对象的元数据:查询方便。

    【讨论】:

      【解决方案3】:

      除其他外,我还使用它们来指定在运行时读取的 EBNF,以动态创建自定义解析器,并指定有关数据库字段的元数据。

      我发现我经常使用自定义属性的一种“模式”是替换枚举,尤其是当代码中差异位置中的枚举依赖于枚举时。

      例如我可能有一个对象状态的枚举。基于这种状态,我在代码中可能有 3 或 4 个不同的位置,我会对该枚举进行“切换”并执行一些操作。其他一些开发人员可以通过添加新枚举来轻松引入错误,但不在代码中的其他地方处理其中一个 switch 语句。

      所以为了避免这种情况,我创建了一个自定义属性,声明为静态类。自定义属性在类的静态构造函数中加载到字典中,代码中的所有位置都使用字典而不是 switch 语句。自定义属性构造函数包含每个 switch 语句的“硬编码”值。

      【讨论】:

        【解决方案4】:

        我必须将一些对象序列化为自定义(旧)格式,并且我使用属性来确定应该序列化哪些字段以及如何格式化它们。然后我有了一个序列化器,它可以接收任何具有这些属性的对象并使用反射来格式化它。

        【讨论】:

        • 您并没有真正使用自己的自定义属性,是吗?
        【解决方案5】:

        到目前为止,我还没有真正找到自定义属性的用途。在某些情况下,我认为它们可能合适但没有使用它们,因为显然读取自定义属性所涉及的反射非常昂贵。

        【讨论】:

          【解决方案6】:

          我在“插件”DLL 中的类上放置了自定义属性。这允许框架动态发现可用插件,评估它们是否感兴趣,然后动态加载感兴趣的插件。

          在我们的领域中,该示例是为家庭中的特定车辆建模的插件。一个车辆系列的一个插件实际上可以模拟该车辆系列中的多个车辆模型(例如,“MX-6”、“Probe”)。如果包含一个 ID 或模型名称作为自定义属性数组,我们可以快速忽略任何甚至没有自定义属性的 DLL,然后进一步忽略任何不为感兴趣的车辆建模的 DLL。

          【讨论】:

            【解决方案7】:

            我曾在基于 ActiveRecord 模式开发的一个 ORM 框架中使用它。这与 LINQ、Castle 项目等中可用的实现相同。

            该框架被称为“SkyFramework”,但它不是开源的。

            例如只是一个粗略的例子......

            您也会在其他开源项目中找到类似的示例。

            [Sky.Table ("user")]
            public class User
            {
                [Sky.Column ("username")]
                public string UserName;
            
                [Sky.Column ("pwd")]
                public string Password;
            }
            

            注意:属性“Table”、“Columns”是当时的自定义属性。

            ActiveRecord 引擎为这些属性解析对象,并为 CRUD...等生成相应的函数...

            同样,我开发了一些自定义属性来识别需要进行基准测试的代码部分......例如......

            [Sky.BenchMark()]
            public void LongRunningMethod(..)
            {
            }
            

            用上述属性标记的方法会自动进行基准标记并生成日志。这些是一些早期的实现。

            有一本关于该主题的 Apress 书籍。 Applied .NET Attribues可能对你有帮助。

            【讨论】:

            • 属性是你写的吗?
            • Table、Column、BenchMark 等都是从 Attribute 类派生的对象。除了解析器引擎负责处理它。这些对象总是被一些工厂类实例化,这样你就可以得到方法的钩子。
            • 请不要与您现在拥有的 LINQ 的类似属性混淆。这是一段旧代码,其属性位于它自己的命名空间中。
            猜你喜欢
            • 2011-01-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多