如果我有这样的 POCO:
[Poco]
public class MyPoco
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
}
...它是这样初始化的:
new MyPoco { FirstName = "Joe", LastName="Bloggs", Address="123 Abc St." }
我能否在 NDepend 中使用 CQL,确保仅使用上述对象初始化程序设置属性,而不是单独设置。
我正试图捕捉这样的代码:
myPoco.FirstName="John";
doSomething(myPoco);
...我不希望人们在现有的 POCO 上设置属性。我知道我可以将 setter 设置为 private
,但我不喜欢在构造函数中传递所有属性,因为您最终会得到一个签名,例如 MyPoco(string, string, string)
- 更容易错位参数(比使用对象初始化语法更容易)
所以,我想使用 NDepend 捕捉它。这是我的 CQL 查询的开始:
from f in JustMyCode.Fields.Where(f=>
f.ParentType.HasAttribute ("JetBrains.Annotations.PocoAttribute".AllowNoMatch()))
where f.MethodsAssigningMe [I'M STUMPED HERE]
看起来我可以分析设置 POCO 属性的方法,但我需要更进一步并检查代码块以查看它是否在对象初始化程序 block 中。
这可能吗?
最佳答案
我不知道您是否可以在 CQL 中执行此操作,尽管即使您不能,您也可以使用 Roslyn 执行此操作。
但是,您可能需要考虑改用构建器模式:
var poco = new MyPoco.Builder { FirstName = "Joe",
LastName="Bloggs",
Address="123 Abc St." }.Build();
现在 poco 本身可以是不可变的,但是构建器可以在任何你喜欢的地方设置属性。
哎呀,如果你是隐式转换的粉丝,你可以甚至有一个从构建器到 poco 的隐式转换:
MyPoco poco = new MyPoco.Builder { FirstName = "Joe",
LastName="Bloggs",
Address="123 Abc St." };
虽然我完全支持验证正确编码的工具,但在无法设计类型以避免一开始就被滥用的情况下,我更希望有一个白痴证明的 API 开始:)
另请注意,在 C# 4 中使用命名参数,甚至可以明确构造函数版本:
var poco = new MyPoco(firstName: "Joe",
lastName: "Bloggs",
address: "123 Abc St.");
当然,这仍然允许人们在没有命名参数的情况下编写它...
关于c# - 我可以强制 POCO 中的字段只在类型初始化程序中设置吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24322955/