我有一个 WCF 客户端,它将自我跟踪实体传递给使用 MVVM 构建的 WPF 应用程序。应用程序本身有一个动态界面。用户可以根据他们所处的角色或他们正在执行的任务来选择他们希望在其工作区中显示哪些对象。
我的自跟踪实体有很多导航属性,其中很多是不需要的。由于其中一些对象可能非常大,我只想在请求时加载这些属性。
我的应用程序如下所示:
[WCF] <---> [ClientSide Repository] <---> [ViewModel] <---> [View]
我的模型是自我跟踪实体。客户端存储库在将模型返回给请求它的 ViewModel 之前连接了一个 LazyLoad 方法(如果需要)。所有 WCF 服务调用都是异步的,这意味着 LazyLoad 方法也是异步的。
LazyLoad 的实际实现给我带来了一些麻烦。这是我想出的选项。
编辑 - 我删除了代码示例以尝试使其更易于阅读和理解。如果您想查看,请查看以前版本的问题
选项 A
在 Getter 中从 WCF 服务器异步延迟加载模型的属性
好:按需加载数据非常简单。XAML 中的绑定会加载数据,因此如果控件在屏幕上,则数据会异步加载并在其存在时通知 UI。如果没有,则不会加载任何内容。例如,<ItemsControl ItemsSource="{Binding CurrentConsumer.ConsumerDocuments}" />
将加载数据,但是如果界面的 Documents 部分不存在,则不会加载任何内容。
错误:在启动之前无法在任何其他代码中使用此属性,因为它将返回一个空列表。例如,如果尚未加载文档,则以下调用将始终返回 false。
public bool HasDocuments
{
get { return ConsumerDocuments.Count > 0; }
}
选项 B
需要时手动调用加载数据
好:易于实现 - 只需添加LoadConsumerDocumentsSync()
和LoadConsumerDocumentsAsync()
方法
不好:必须记住在尝试访问数据之前加载数据,包括在绑定中使用数据时。这可能看起来很简单,但它很快就会失控。例如,每个 ConsumerDocument 都有一个 UserCreated 和 UserLastModified。有一个 DataTemplate 定义了带有 ToolTip 的 UserModel,其中显示了额外的用户数据,例如扩展名、电子邮件、团队、角色等。因此,在显示文档的 ViewModel 中,我必须调用LoadDocuments
,然后遍历它们并调用LoadConsumerModified
and LoadConsumerCreated
。它也可以继续下去……在那之后我不得不LoadUserGroups
和LoadUserSupervisor
。它还存在循环循环的风险,其中 aUser
有一个Groups[]
属性,而 aGroup
有一个Users[]
属性
选项 C
到目前为止我最喜欢的选择...创建两种访问属性的方法。一个同步和一个异步。将对 Async 属性进行绑定,并且任何代码都将使用 Sync 属性。
好:数据根据需要异步加载 - 正是我想要的。也没有太多额外的编码,因为我需要做的就是修改 T4 模板以生成这些额外的属性/方法。
不好:有两种方法来访问相同的数据似乎效率低下且令人困惑。您需要记住何时应该使用Consumer.ConsumerDocumentsAsync
而不是Consumer.ConsumerDocumentsSync
. WCF 服务调用也有可能多次运行,这需要为每个导航属性添加一个额外的 IsLoaded 属性,例如 IsConsumerDocumentsLoaded。
选项 D
跳过异步加载,只需在设置器中同步加载所有内容。
好:很简单,不需要额外的工作
不好:数据加载时会锁定 UI。不想要这个。
选项 E
让某人告诉我还有另一种方法可以做到这一点并指出我的代码示例:)
其他注意事项
一些 NavigationProperties 将在将对象返回给客户端之前加载到 WCF 服务器上,但是其他的太昂贵而无法使用。
除了在选项 C 中手动调用 Load 事件之外,这些都可以通过 T4 模板完成,因此我几乎不需要编写代码。我所要做的就是在客户端存储库中连接 LazyLoad 事件并将其指向正确的服务调用。