客户端代码生成
当使用 WCF RIA Services 链接 Silverlight 项目和中间层项目时,RIA Services 将基于您在中间层中公开的实体和操作为客户端应用程序生成客户端代理类。由于 RIA Services 会生成这些类,因此您不必将任何应用程序逻辑从中间层复制到表示层。在重新生成客户端项目时,您对中间层代码进行的所有更改都将与表示层代码同步。在向解决方案添加 RIA Services 链接时,将向该解决方案添加显式生成依赖项,强制在生成客户端项目的代码之前先生成服务器项目。
生成的代码驻留在客户端项目中名为 Generated_Code 的文件夹中。若要查看此文件夹,您必须为该客户端项目选择**“解决方案资源管理器”窗口中的“显示所有文件”**。不应直接修改 Generated_Code 文件夹中的类,因为在重新生成客户端项目时将覆盖这些类。但是,您可以打开所生成的文件,以查看可用于客户端项目的代码。
用于生成客户端代码的算法遵循以下这些基本规则:
分析由中间层项目生成或引用且适用于域服务类、实体类或共享代码的所有程序集。
针对使用 EnableClientAccessAttribute 特性批注的每个域服务,生成一个从 DomainContext 类派生的类。
针对域服务类中的每个查询方法、命名更新方法(UsingCustomMethod 属性设置为 true 的更新方法)或调用操作,在域上下文类中生成一个方法。
对于域服务公开的每个实体类,生成一个实体代理类。查询方法在返回实体类时将公开该实体类。
复制标记为要共享到客户端项目的代码。
下图显示为中间层项目生成的客户端代码。
DomainService 和 DomainContext
根据以下规则,将为每个域服务类生成从 DomainContext 派生的一个类:
将使用与域服务相同的命名空间生成域上下文类。
域上下文类包含三个构造函数:
默认构造函数,用于嵌入使用 WebDomainClient 类基于 http 与域服务通信时所需的 URI。
用于允许客户端指定备用 URI 的构造函数。
用于允许客户端提供自定义 DomainClient 实现(通常用于单元测试或重定向到自定义传输层)的构造函数。
对于域服务类中的每个查询方法,生成一个 EntityQuery 方法,在客户端项目中可以使用该方法来加载实体。
对于每个调用操作,生成一个相应的 InvokeOperation 方法,该方法可用于异步调用该操作。
对每个标记有 Update(UsingCustomMethod=true) 特性的方法生成相应的方法,以调用带特性标记的方法以及确定其是否已调用。
域服务中用于执行插入、更新或删除操作的公共方法导致在域上下文中生成的 EntityContainer 带有 EntitySetOperations 标志,该标志指示在客户端上允许执行哪些操作。
实体类和实体代理类
在生成实体代理类时适用以下规则:
生成的代理类具有与中间层中的实体类相同的名称和命名空间。
根实体类型派生自该实体类。派生的实体类型派生自中间层所公开的相应基类型。
在代理类中生成包含受支持类型和未使用实体类中的 ExcludeAttribute 特性标记的各个公共属性,除非客户端项目中已存在该属性。有关更多信息,请参见本主题后面的“避免重复的成员”一节。Object 是不受支持的类型。
每个属性 setter 将包含特定代码,用于执行验证并通知客户端该属性正在更改或已更改。
在生成的代码中,元数据特性与实体类组合在一起。客户端上将不存在元数据类。
如果可能,自定义特性将传播到代理类。有关为使客户端项目中存在自定义特性而必须符合的前提条件的说明,请参见下面的“自定义特性”一节。
如果为该成员的多个 CustomValidationAttribute 实例指定了相同的类型和验证方法,则仅有一个 CustomValidationAttribute 传播到该成员。
自定义特性
如果添加自定义特性不会导致客户端项目中出现编译错误,则这些自定义特性将传播到代理类。对于要传播的自定义特性,必须满足以下条件:
自定义特性类型必须在客户端项目中可用。
在自定义特性声明中指定的任何类型都必须在客户端项目中可用。
自定义特性类型必须公开其所有属性的公共 setter;或公开一个构造函数,允许设置不具有公共 setter 的属性。
如果所需的自定义特性未传播到客户端,则可能需要在客户端项目中添加程序集引用。为了在客户端项目中编译自定义特性,需要添加对任何所需的程序集的引用。还可以通过在共享文件中定义自定义特性在各层间共享该自定义特性。
共享代码
在中间层和表示层之间共享代码文件时,代码将不进行任何更改直接复制到客户端项目。通过采用 *.shared.cs
或 *.shared.vb
的模式对文件命名来指定要共享的文件。包含共享文件的中间层项目的目录结构将复制到 Generated_Code 文件夹中。
当您添加共享代码文件中的某个自定义类型,然后再从调用操作返回该类型时,在域上下文中生成的方法不会返回该自定义类型。域上下文中的这一方法将改为返回框架中的某一类型。例如,当您创建了名为 MyCustomDictionary
的用于实现 IDictionary 的自定义类型并指定该类型作为域操作的返回值时,在该域上下文中生成的方法不会返回 MyCustomDictionary
。它将改为返回一个 Dictionary 对象。
有关更多信息,请参见共享代码。
避免重复的成员
在生成实体代理类时,有可能已使用分部类型在客户端项目中定义了相同的类型和成员。您可能已经在共享代码或仅存在于客户端项目中的代码中定义了该成员。RIA Services 将在生成代理类之前检查现有成员。不会在代理类中生成任何已定义的成员。