您在现实世界中将自定义 .NET 属性用于哪些方面?
我已经阅读了几篇关于它们的文章,但我从未使用过自定义属性。
我觉得当它们有用时我可能会忽略它们。
我说的是您创建的属性,而不是已经包含在框架中的属性。
您在现实世界中将自定义 .NET 属性用于哪些方面?
我已经阅读了几篇关于它们的文章,但我从未使用过自定义属性。
我觉得当它们有用时我可能会忽略它们。
我说的是您创建的属性,而不是已经包含在框架中的属性。
我创建了一个脚本引擎,并用 [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>>
我已经使用它们“自定义”属性进行验证(即使用我自己的“信用卡验证”标记要验证的字段)和我编写的自定义 LinqToLucene 分析器(即指定在给定字段上使用哪个分析器) .
例如,验证代码如下所示:
public class Customer
{
[CreditCardValidator]
string creditCardNumber;
[AddressValidator]
string addressLineOne
}
验证上述对象时,由于“自定义”属性,每个字段都使用适当的验证器进行验证。
在我编写的 LinqToLucene 东西中,自定义属性很好,因为它们允许您在运行时(通过反射)查找特定字段。例如,如果您有一个客户对象,您可能有兴趣获取已标记为“索引我”的所有属性:自定义属性让您可以轻松完成此操作,因为它以一种方式公开有关该对象的元数据:很容易查询。
除其他外,我使用它们来指定在运行时读取的 EBNF,以动态创建自定义解析器,并指定有关数据库字段的元数据。
我发现我通常使用自定义属性的一种“模式”是替换枚举,尤其是当代码中的差异位置中的枚举依赖于枚举时。
例如,我可能有一个对象状态的枚举。基于这种状态,我在代码中可能有 3 或 4 个不同的位置,我会对该枚举进行“切换”并执行一些操作。其他一些开发人员可以很容易地通过添加一个新的枚举来引入一个错误,但不在代码中的其他地方处理其中一个 switch 语句。
因此,为了避免这种情况,我创建了一个声明为静态类的自定义属性。自定义属性在类的静态构造函数中加载到字典中,代码中的所有位置都使用字典而不是 switch 语句。自定义属性构造函数包含每个 switch 语句的“硬编码”值。
我必须将一些对象序列化为自定义(传统)格式,并且我使用属性来确定应该序列化哪些字段以及如何格式化它们。然后我有一个序列化程序,它可以获取具有这些属性的任何对象并使用反射来格式化它。
我曾在基于 ActiveRecord 模式开发的一个 ORM 框架中使用它。这与 LINQ、Castle 项目等中可用的实现相同。
该框架被称为“SkyFramework”,但它不是开源的。
例如,只是一个粗略的例子......
您也会在其他开源项目中找到类似的示例。
[Sky.Table ("user")]
public class User
{
[Sky.Column ("username")]
public string UserName;
[Sky.Column ("pwd")]
public string Password;
}
注意:属性“表”、“列”是当时的自定义属性。
ActiveRecord 引擎解析这些属性的对象并为 CRUD 生成相应的函数......等等......
同样,我开发了一些自定义属性来识别需要进行基准测试的代码部分……例如。
[Sky.BenchMark()]
public void LongRunningMethod(..)
{
}
标有上述属性的方法会自动进行基准标记并生成日志。这些是一些较早的实现。
有一本关于该主题的 Apress 书籍 。Applied .NET Attribues 可能对您有所帮助。
到目前为止,我还没有真正找到自定义属性的用途。在某些情况下,我认为它们可能是合适的,但没有使用它们,因为显然读取自定义属性所涉及的反射非常昂贵。
我在“插件”DLL 中的类上放置了自定义属性。这允许框架动态发现可用插件,评估它们是否感兴趣,然后动态加载感兴趣的插件。
在我们的领域中,示例是模拟家庭中特定车辆的插件。一个车辆系列的一个插件实际上可以模拟该车辆系列中的多个车辆模型(例如,“MX-6”、“Probe”)。如果将 ID 或模型名称作为自定义属性数组包含在内,我们可以快速忽略任何甚至没有自定义属性的 DLL,然后进一步忽略任何不为感兴趣的车辆建模的 DLL。