如果我有这样的 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.");

但是当然这仍然允许人们在没有命名参数的情况下编写它......

关于c# - 我可以强制 POCO 中的字段只在类型初始值设定项中设置吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24322955/

10-12 12:38
查看更多