[notice:图片上传不好使,等好使了我再加上]
最近开始学习RIAService,先说安装。本来今天刚在博客园上看到一篇有讲RIA安装的。但好像很复杂,要先把SL等都卸载了才行。但是我安装的时候超级简单,首先在下载安装包(点此处),然后一路Next下来就好了。我也不知道为什么,我的环境是Win7+VS2008SP1+Silverlight3+Experssion Studio3。
这篇文章的内容基本来是RiaServiceOverviewPreview文档,已经有牛人在园子做翻译了,如:
微软RIA服务2009年7月预览版官方手册第1节(翻译:戴石麟)
微软RIA服务2009年7月预览版官方手册第2节(翻译:戴石麟)
Microsoft .NET RIA Services快速上手
我这里的东西是紧接微软RIA服务2009年7月预览版官方手册第2节(翻译:戴石麟)的。虽然他马上肯定就要翻译,但我也献个丑。不要期望有什么我的心得,都是从文档里学的。
言归正转,首先我们建立一个依赖于RIA Link的Sliverlight应用程序GeneratedCode。其中SL工程是client端(client-tier),Web工程是server端(mid-tier).
现在我们来模拟整个Code-Generation(CG,我自己的简写,让我想起了GC)过程。
1.在server建立一个数据实体Person类,有两个属性:FristName,LastName,我把它放在Server的Data文件夹下(Persion.cs):
1public partial class Person
2{
3 [Key]
4 public string FristName { get; set; }
5
6 [Key]
7 public string LastName { get; set; }
8
9}
10 为了识别KeyAttribute属性,将要引用System.ComponentModel.DataAnnotations.dll并引用此命名空间,[Key]的作用唯一标识实体对象的值。
2.在server端建立一个示例数据的生成器,用于得到具体的数据(PersionData.cs)
PersonData
1public class PersonData
2{
3
4List<Person> persons = new List<Person>(
5new Person[]
6 {
7 new Person() { FristName = "JR", LastName = "Smith" },
8 new Person() { FristName="Jack",LastName="Chan"}
9 });
10public IList<Person> Persons
11{
12 get
13 {
14 return persons;
15 }
16}
17
18}
19 3.好了,现在我们来建立RiaService(PersonService.cs)。我们要把服务端的数据的属性,方法暴露给服务器端,中间,需要一个服务和一个代理,其中的服务派生自DomainService,位于服务端。;
Code
1namespace GeneratedCode.Web.Data
2{
3 [EnableClientAccess]
4 public class PersionService:DomainService
5 {
6 private PersonData _personData = new PersonData();
7
8 public IEnumerable<Person> GetPersons()
9 {
10 return _personData.Persons;
11 }
12 }
13}
14 这里要注意两点:1)该类应继承自DoaminService(位于System.Web.DomainServices下)以被识别为RIA服务。2)该类要增加[EnableClientAccess]属性,以便客户端能够访问该类以及方法(位于Syste.Web.Ria下)
4.现在我们就可以看看RIA的CG功能如何了,Builde整个解决方案,并选中GeneratedCode工程,然后[Project]->[Show All Files]把生成的文件显示出来(注意:一定要选中工程,选中解决方案是不行的,会找不到Show All Files菜单。让我们来看看都生成了些什么:
可以看到在GeneratedCode工程(Silverlight工程)中生成了一个名叫Generated_code的文件夹(bin,obj不关注),并且生成了一个名叫GeneratedCode.Web.g.cs的文件名。这是一个以你的Web工程的名字开头的的cs文件(Web工程名.g.cs),g代表这是自动生成的文件(Generate code),打开看一看里面的内容(代码过长,在最后):
1)首先是一个继承自RiaContextBase的RiaContext类,我们暂不管他
2)然后是一个继承自DomainContext的PersonContext类,他是重点,这就是之前所说的客户端于服务端(DomainService)的代理,他有三个构造函数
(1)PersionContext():默认构造函数,用默认的数据服务Uri
(2)public PersionContext(Uri serviceUri) : 用一个指定的数据服务Uri
(3)public PersionContext(DomainClient domainClient) : 用一个指定的DomainClient实例构造
接着往下看,我们看到了什么?没错是:
Code
1public EntityList<Person> Persons
2{
3 get
4 {
5 return base.Entities.GetEntityList<Person>();
6 }
7}
8public EntityQuery<Person> GetPersonsQuery()
9{
10 return base.CreateQuery<Person>("GetPersons", null, false, true);
11}
显然,上速两个函数就把PersonService的方法“代理”过来了。这就意味着,在客户端我们可以用PersonContext的方法最终调用到PersonService的方法,然后得到数据。、
(4)我们再往下看,看到了一个继承自实体Entity的Person类(实体代理类)。里面包含了Person类的属性,并加上了[Key()]和[DataMember]属性。此类是实体类找客户端代理实体类,与实体类同名,包含了实体因所有的公开属.
5.最后我们来总结一下RIAService的CG:
1)哪些会CG
(1)所有服务端引用的程序集都会被分析
(2)所有继承自DomainService和标记主[EnableClientAccess]属性的类也会被分析
(3)(2)中的那样的类的所有公有方法也会被分析,以决定将在客户端上以一种什么样的实体形式来呈现
2)怎么CG
(1)实体代理类(客户端继承自Entity的Person类)会与实体类(服务端的Person类)共用同一个namespace,
(2)实体代理类与实体类的名称相同(都为Person)
(3)实体类的每个公有属性都会在实代理类暴露出来(FristName,LastName)
(4)实体类用户定义的属性都会在实体代理类得以呈现(本文未提及)
6.结语
好了,第一部分的CG就到这里吧,敬请拍砖,下次将是Metadata与Shared Code的CG。
Code
1//------------------------------------------------------------------------------
2// <auto-generated>
3// This code was generated by a tool.
4// Runtime Version:2.0.50727.4927
5//
6// Changes to this file may cause incorrect behavior and will be lost if
7// the code is regenerated.
8// </auto-generated>
9//------------------------------------------------------------------------------
10
11namespace GeneratedCode
12{
13 using System;
14 using System.Collections.Generic;
15 using System.ComponentModel;
16 using System.ComponentModel.DataAnnotations;
17 using System.Linq;
18 using System.Web.Ria.Data;
19 using System.Windows.Ria.Data;
20
21
22 /**//// <summary>
23 /// Context for the RIA application.
24 /// </summary>
25 /// <remarks>
26 /// This context extends the base to make application services and types available
27 /// for consumption from code and xaml.
28 /// </remarks>
29 public sealed partial class RiaContext : System.Windows.Ria.RiaContextBase
30 {
31
32 Extensibility Method Definitions#region Extensibility Method Definitions
33
34 /**//// <summary>
35 /// This method is invoked from the constructor once initialization is complete and
36 /// can be used for further object setup.
37 /// </summary>
38 partial void OnCreated();
39
40 #endregion
41
42
43 /**//// <summary>
44 /// Initializes a new instance of the RiaContext class.
45 /// </summary>
46 public RiaContext()
47 {
48 this.OnCreated();
49 }
50
51 /**//// <summary>
52 /// Gets the context that is registered as a lifetime object with the current application.
53 /// </summary>
54 /// <exception cref="InvalidOperationException"> is thrown if there is no current application,
55 /// no contexts have been added, or more than one context has been added.
56 /// </exception>
57 /// <seealso cref="Application.ApplicationLifetimeObjects"/>
58 public new static RiaContext Current
59 {
60 get
61 {
62 return ((RiaContext)(System.Windows.Ria.RiaContextBase.Current));
63 }
64 }
65 }
66}
67namespace GeneratedCode.Web.Data
68{
69 using System;
70 using System.Collections.Generic;
71 using System.ComponentModel;
72 using System.ComponentModel.DataAnnotations;
73 using System.Linq;
74 using System.Runtime.Serialization;
75 using System.Web.Ria.Data;
76 using System.Windows.Ria.Data;
77
78
79 public sealed partial class PersionContext : DomainContext
80 {
81
82 Extensibility Method Definitions#region Extensibility Method Definitions
83
84 /**//// <summary>
85 /// This method is invoked from the constructor once initialization is complete and
86 /// can be used for further object setup.
87 /// </summary>
88 partial void OnCreated();
89
90 #endregion
91
92
93 /**//// <summary>
94 /// Default constructor.
95 /// </summary>
96 public PersionContext() :
97 this(new HttpDomainClient(new Uri("DataService.axd/GeneratedCode-Web-Data-PersionService/", System.UriKind.Relative)))
98 {
99 }
100
101 /**//// <summary>
102 /// Constructor used to specify a data service URI.
103 /// </summary>
104 /// <param name="serviceUri">
105 /// The PersionService data service URI.
106 /// </param>
107 public PersionContext(Uri serviceUri) :
108 this(new HttpDomainClient(serviceUri))
109 {
110 }
111
112 /**//// <summary>
113 /// Constructor used to specify a DomainClient instance.
114 /// </summary>
115 /// <param name="domainClient">
116 /// The DomainClient instance the DomainContext should use.
117 /// </param>
118 public PersionContext(DomainClient domainClient) :
119 base(domainClient)
120 {
121 this.OnCreated();
122 }
123
124 public EntityList<Person> Persons
125 {
126 get
127 {
128 return base.Entities.GetEntityList<Person>();
129 }
130 }
131
132 /**//// <summary>
133 /// Returns an EntityQuery for query operation 'GetPersons'.
134 /// </summary>
135 public EntityQuery<Person> GetPersonsQuery()
136 {
137 return base.CreateQuery<Person>("GetPersons", null, false, true);
138 }
139
140 protected override EntityContainer CreateEntityContainer()
141 {
142 return new PersionContextEntityContainer();
143 }
144
145 internal sealed class PersionContextEntityContainer : EntityContainer
146 {
147
148 public PersionContextEntityContainer()
149 {
150 this.CreateEntityList<Person>(EntityListOperations.None);
151 }
152 }
153 }
154
155 [DataContract(Namespace="http://schemas.datacontract.org/2004/07/GeneratedCode.Web.Data")]
156 public sealed partial class Person : Entity
157 {
158
159 private string _fristName;
160
161 private string _lastName;
162
163 Extensibility Method Definitions#region Extensibility Method Definitions
164
165 /**//// <summary>
166 /// This method is invoked from the constructor once initialization is complete and
167 /// can be used for further object setup.
168 /// </summary>
169 partial void OnCreated();
170 partial void OnFristNameChanging(string value);
171 partial void OnFristNameChanged();
172 partial void OnLastNameChanging(string value);
173 partial void OnLastNameChanged();
174
175 #endregion
176
177
178 /**//// <summary>
179 /// Default constructor.
180 /// </summary>
181 public Person()
182 {
183 this.OnCreated();
184 }
185
186 [DataMember()]
187 [Key()]
188 public string FristName
189 {
190 get
191 {
192 return this._fristName;
193 }
194 set
195 {
196 if ((this._fristName != value))
197 {
198 this.ValidateProperty("FristName", value);
199 this.OnFristNameChanging(value);
200 this.RaiseDataMemberChanging("FristName");
201 this._fristName = value;
202 this.RaiseDataMemberChanged("FristName");
203 this.OnFristNameChanged();
204 }
205 }
206 }
207
208 [DataMember()]
209 [Key()]
210 public string LastName
211 {
212 get
213 {
214 return this._lastName;
215 }
216 set
217 {
218 if ((this._lastName != value))
219 {
220 this.ValidateProperty("LastName", value);
221 this.OnLastNameChanging(value);
222 this.RaiseDataMemberChanging("LastName");
223 this._lastName = value;
224 this.RaiseDataMemberChanged("LastName");
225 this.OnLastNameChanged();
226 }
227 }
228 }
229
230 public override object GetIdentity()
231 {
232 return EntityKey.Create(this._fristName, this._lastName);
233 }
234 }
235}
236