虚拟代理如何工作?

时间:2011-06-15 19:43:11

标签: c# wcf proxy virtual

我在围绕虚拟代理问题时遇到了一些麻烦。我已经阅读了大量的文章,并花了几个小时试图找到好的信息,但我还没有找到一些全面的东西。因此,我将在此处提出一般性请求以获取更好的信息(在此处发布或仅发布链接)。我还将在下面添加一些细节,以便更好地解释我想要的是什么。

我有几个对象,它们之间有很多引用。为了简洁起见,我将有一个具有基本父子关系的对象(Node)。当我从数据库中提取此对象时,我想实现延迟加载。根据我的阅读,虚拟代理将基本上通过引用接口(INode)并根据需要提取数据成员来处理所有延迟加载。 [注意:我实际上没有INode类,但是当我将virtual关键字放在我的数据成员上时,似乎确实使用了代理]

当我在我的类虚拟中创建数据成员时,它似乎是一个代理。这是虚拟代理吗?这些是否实现了延迟加载?

我搜索了有关virtual关键字的信息,但是我能找到的唯一文档是在方法上使用它,用于继承,以便派生类可以覆盖函数,这与我想要的无关(我想)。

这是我目前的Node.cs

[DataContract(IsReference=true)]
public partial class Node
{
  [DataMember]
  public long ID { get; private set; }
  [DataMember]
  public virtual Node Parent { get; set; }
  [DataMember]
  public virtual ICollection<Node> Children { get; set; }
}

基本上在这一点上我很困惑,只需要一些关于这个主题的指导,甚至是我可以看到的在线资源,因为我发现的所有内容都没那么有用。

提前致谢。

2 个答案:

答案 0 :(得分:5)

“虚拟”代理和延迟加载与ORM工具有关。代理实际上不是虚拟的,它是动态的,它遵循由GoF定义的真实代理模式。

动态代理是ORM工具在运行时创建的类(它没有在任何地方定义为代码文件)。它派生自您的实体,它会覆盖导航属性。因此,他们必须是虚拟的才能使代理工作。代理在私有字段或任何更复杂的结构中保存导航属性状态,如果在第一次看到状态被卸载时访问该属性并触发从数据库加载并将状态更改为已加载。

无论如何,我不确定这是如何引用WCF的,因为最佳做法是不使用延迟加载WCF。为什么呢?

  • 如果在服务器端使用延迟加载序列化将始终从数据库整个对象图中提取,因为序列化将访问每个导航属性并触发延迟加载,但它将开始序列化延迟加载的实体并访问其所有导航属性等。 / LI>
  • 客户端的延迟加载是模糊的。首先,客户端的延迟加载完全取决于您 - 您必须实现它。使用服务时,您应该始终遵循SOA原则之一:服务边界是明确的。这意味着您的对象的用户应始终知道他正在进行远程呼叫而不是本地呼叫。分布式计算的主要目标是减少网络往返,因此如果可能,您应该使用预先加载并在单个往返中传输所有需要的数据,而不是使用延迟加载。这同样适用于从数据库加载 - 在有意义时使用延迟加载,因为对数据库的roundrips可能是昂贵的操作。

答案 1 :(得分:1)

我认为你想要一些私人领域支持你的虚拟专业。在这些虚拟属性的覆盖中,您检查私有字段以查看它当前是否有效(它是否已经从db获得,是否是最新的等) - 如果没有,则获取或重新获取它。我不认为它已经不复存在了。

基类:

private Node _Parent;
public virtual Node Parent { 
    get { return _Parent; } // Default no lazy fetch.
}

覆盖:

public override Node Parent {
    get {
        if (_Parent==null) // or out of date, dirty etc
            Do_db_get_of_parent();
        return _Parent;
    }
}