【问题标题】:Altering lazy-loaded object's private variables更改延迟加载对象的私有变量
【发布时间】:2010-04-04 02:27:35
【问题描述】:

我在使用 NHibernate 和延迟加载时遇到了私有设置器的问题。假设我有一个如下所示的类:

public class User
{
    public virtual int Foo {get; private set;}
    public virtual IList<User> Friends {get; set;}

    public virtual void SetFirstFriendsFoo()
    {
        // This line works in a unit test but does nothing during a live run with
        // a lazy-loaded Friends list
        Friends(0).Foo = 1; 
    }
}

SetFirstFriendsFoo 调用在单元测试中完美运行(从 objects of the same type can access each others private properties 开始就应该如此)。

但是,当使用延迟加载的好友列表实时运行时,SetFirstFriendsFoo 调用会静默失败。我猜这是因为在运行时,Users(0).Foo 对象不再是 User 类型,而是继承自 User 的代理类,因为 Friends 列表是延迟加载的。

我的问题是:这不应该产生运行时异常吗?如果您尝试访问另一个类的私有属性,则会出现编译时异常,但是当您遇到这样的情况时,应用程序似乎会忽略您并继续前进。

注意:如果我将“私有集”更改为“受保护集”,一切正常。

【问题讨论】:

  • 你的意思是Friends[0].Foo = 1;而不是Users(0).Foo = 1;
  • 是的。解决了这个问题。很抱歉造成混乱。
  • 因为私有方法不能被代理,而受保护的方法可以?

标签: c# nhibernate accessibility


【解决方案1】:

正如 Paco 指出的那样,只能代理虚拟方法/属性,而 C# 不允许虚拟私有成员。

您可以通过反射访问它,但我的第一个想法是您应该尽量避免它。尽管如此,如果你想去那里,你需要一些类似的东西:

// edit: fixed to use GetType
Type type = Friend[ 0 ].GetType().BaseType;
type.GetProperty("Foo",BindingFlags.Instance|BindingFlags.NonPublic).SetValue( Friends[0], 1, null );

或者,您可以使用Fasterflect 并执行相同的操作:

Friends[ 0 ].SetPropertyValue( "Foo", 1 );

【讨论】:

  • 我忘记在我的属性前添加“虚拟”关键字。这会改变一切吗?它仍然是公共虚拟属性,但 setter 是私有的。
  • 据我所知 NHibernate 使用 Windsor 来生成它的代理,因此请查看文档以了解它到底支持什么。但是为什么不让属性设置器受保护而不是私有呢?无论如何,反射都可以用来打破你的封装,所以在这里寻求务实的解决方案可能是个好主意。
猜你喜欢
  • 2017-10-31
  • 2011-02-06
  • 1970-01-01
  • 1970-01-01
  • 2016-05-04
  • 1970-01-01
  • 2018-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多