我可以强制POCO中的字段只在类型初始化器中设置吗?
本文关键字:类型 初始化 设置 POCO 字段 我可以 | 更新日期: 2023-09-27 18:09:44
如果我有这样一个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的属性,但我需要更进一步,检查代码块,看看它是否在对象初始化块中。
这可能吗?
我不知道你是否可以在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.");
但是当然,仍然允许的人不用命名参数来写它。