在.Net中使用私有set初始化属性

6
public class Foo
{
    public string Name { get; private set;} // <-- Because set is private,
}

void Main()
{
    var bar = new Foo {Name = "baz"}; // <-- This doesn't compile
    /*The property or indexer 'UserQuery.Foo.Name' cannot be used 
      in this context because the set accessor is inaccessible*/

    using (DataContext dc = new DataContext(Connection))
    {
        // yet the following line works.  **How**?
        IEnumerable<Foo> qux = dc.ExecuteQuery<Foo>(
           "SELECT Name FROM Customer");
    }
    foreach (q in qux) Console.WriteLine(q);
}

我之前一直使用private修饰符,因为它能够正常工作并避免我在代码中犯错。但是现在我需要创建一个新的Foo,所以我将属性中的private修饰符删除了。我非常好奇,为什么ExecuteQuery可以将结果转换成IEnumerable?
编辑:好的,私有修饰符无法阻止反射访问setter方法。从答案中得知,ExecuteQuery(或者说数据上下文)使用反射获取属性名称并忽略修饰符。有没有办法验证这一点?我该如何自己找出来呢?(添加反射到标签列表中)
3个回答

4
在Foo上创建一个构造函数,接受一个“Name”值:
public class Foo
{
    public Foo(string name)
    {
        Name = name;
    }

    public string Name { get; private set; }
}

现在按照以下方式构建您的Foo:
var bar = new Foo("baz");

编辑(阅读您问题的其余部分)

我的猜测是ExecuteQuery使用反射来检查类并找到其属性。它可能不关心Name上的setter是私有的-只要Name有一个setter。


这是正确的。您可以使用GetSetMethod(true)PropertyInfo轻松获取私有setter方法。我非常确定这就是Linq to SQL所做的。 - Aaronaught

4
这里是一个简单的代码片段,展示这种行为:
class Blah {
  public string Property { get; private set; }
}

var blah = new Blah();
typeof(Blah).GetProperty("Property").SetValue(blah, "newValue", null);
// at this stage blah.Property == "newValue"

1

查询是针对一个数据存储进行评估的,该存储没有公共或私有的概念。即使在代码中,也可以使用一种称为反射的技术访问私有成员。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接