RIAService学习笔记:理解 RIA Service Client端的代码生成(Code Generation)(一)

本文详细介绍RIAService的安装步骤及代码生成(Code Generation, CG)的过程。通过创建一个简单的示例应用,展示如何定义服务端实体类、生成数据实体及服务类,并实现客户端与服务端的交互。
[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):

 1 public   partial   class  Person
 2 ExpandedBlockStart.gifContractedBlock.gif {
 3    [Key]
 4ExpandedSubBlockStart.gifContractedSubBlock.gif    public string FristName getset; }
 5
 6    [Key]
 7ExpandedSubBlockStart.gifContractedSubBlock.gif    public string LastName getset; }
 8
 9}

10

为了识别KeyAttribute属性,将要引用System.ComponentModel.DataAnnotations.dll并引用此命名空间,[Key]的作用唯一标识实体对象的值。

2.在server端建立一个示例数据的生成器,用于得到具体的数据(PersionData.cs)


ContractedBlock.gif ExpandedBlockStart.gif PersonData
 1public class PersonData
 2ExpandedBlockStart.gifContractedBlock.gif{
 3
 4List<Person> persons = new List<Person>(
 5new Person[]
 6ExpandedSubBlockStart.gifContractedSubBlock.gif     {
 7ExpandedSubBlockStart.gifContractedSubBlock.gif         new Person() { FristName = "JR", LastName = "Smith" },
 8ExpandedSubBlockStart.gifContractedSubBlock.gif         new Person() { FristName="Jack",LastName="Chan"}
 9     }
);
10public IList<Person> Persons
11ExpandedSubBlockStart.gifContractedSubBlock.gif{
12    get
13ExpandedSubBlockStart.gifContractedSubBlock.gif    {
14        return persons;
15    }

16}

17
18}

19

3.好了,现在我们来建立RiaService(PersonService.cs)。我们要把服务端的数据的属性,方法暴露给服务器端,中间,需要一个服务和一个代理,其中的服务派生自DomainService,位于服务端。;


ContractedBlock.gif ExpandedBlockStart.gif Code
 1namespace GeneratedCode.Web.Data
 2ExpandedBlockStart.gifContractedBlock.gif{
 3    [EnableClientAccess]
 4    public class PersionService:DomainService
 5ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 6        private PersonData _personData = new PersonData();
 7
 8        public IEnumerable<Person> GetPersons()
 9ExpandedSubBlockStart.gifContractedSubBlock.gif        {
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实例构造

接着往下看,我们看到了什么?没错是:

ContractedBlock.gif ExpandedBlockStart.gif Code
 1public EntityList<Person> Persons
 2ExpandedBlockStart.gifContractedBlock.gif{
 3    get
 4ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 5        return base.Entities.GetEntityList<Person>();
 6    }

 7}

 8public EntityQuery<Person> GetPersonsQuery()
 9ExpandedBlockStart.gifContractedBlock.gif{
10    return base.CreateQuery<Person>("GetPersons"nullfalsetrue);
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。

ContractedBlock.gif ExpandedBlockStart.gif 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
 12ExpandedBlockStart.gifContractedBlock.gif{
 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    
 22ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <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
 30ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 31        
 32ContractedSubBlock.gifExpandedSubBlockStart.gif        Extensibility Method Definitions#region Extensibility Method Definitions
 33
 34ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <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        
 43ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 44        /// Initializes a new instance of the RiaContext class.
 45        /// </summary>

 46        public RiaContext()
 47ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 48            this.OnCreated();
 49        }

 50        
 51ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <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
 59ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 60            get
 61ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 62                return ((RiaContext)(System.Windows.Ria.RiaContextBase.Current));
 63            }

 64        }

 65    }

 66}

 67namespace GeneratedCode.Web.Data
 68ExpandedBlockStart.gifContractedBlock.gif{
 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
 80ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 81        
 82ContractedSubBlock.gifExpandedSubBlockStart.gif        Extensibility Method Definitions#region Extensibility Method Definitions
 83
 84ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <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        
 93ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
 94        /// Default constructor.
 95        /// </summary>

 96        public PersionContext() : 
 97                this(new HttpDomainClient(new Uri("DataService.axd/GeneratedCode-Web-Data-PersionService/", System.UriKind.Relative)))
 98ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 99        }

100        
101ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <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))
109ExpandedSubBlockStart.gifContractedSubBlock.gif        {
110        }

111        
112ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <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)
120ExpandedSubBlockStart.gifContractedSubBlock.gif        {
121            this.OnCreated();
122        }

123        
124        public EntityList<Person> Persons
125ExpandedSubBlockStart.gifContractedSubBlock.gif        {
126            get
127ExpandedSubBlockStart.gifContractedSubBlock.gif            {
128                return base.Entities.GetEntityList<Person>();
129            }

130        }

131        
132ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
133        /// Returns an EntityQuery for query operation 'GetPersons'.
134        /// </summary>

135        public EntityQuery<Person> GetPersonsQuery()
136ExpandedSubBlockStart.gifContractedSubBlock.gif        {
137            return base.CreateQuery<Person>("GetPersons"nullfalsetrue);
138        }

139        
140        protected override EntityContainer CreateEntityContainer()
141ExpandedSubBlockStart.gifContractedSubBlock.gif        {
142            return new PersionContextEntityContainer();
143        }

144        
145        internal sealed class PersionContextEntityContainer : EntityContainer
146ExpandedSubBlockStart.gifContractedSubBlock.gif        {
147            
148            public PersionContextEntityContainer()
149ExpandedSubBlockStart.gifContractedSubBlock.gif            {
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
157ExpandedSubBlockStart.gifContractedSubBlock.gif    {
158        
159        private string _fristName;
160        
161        private string _lastName;
162        
163ContractedSubBlock.gifExpandedSubBlockStart.gif        Extensibility Method Definitions#region Extensibility Method Definitions
164
165ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <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        
178ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
179        /// Default constructor.
180        /// </summary>

181        public Person()
182ExpandedSubBlockStart.gifContractedSubBlock.gif        {
183            this.OnCreated();
184        }

185        
186        [DataMember()]
187        [Key()]
188        public string FristName
189ExpandedSubBlockStart.gifContractedSubBlock.gif        {
190            get
191ExpandedSubBlockStart.gifContractedSubBlock.gif            {
192                return this._fristName;
193            }

194            set
195ExpandedSubBlockStart.gifContractedSubBlock.gif            {
196                if ((this._fristName != value))
197ExpandedSubBlockStart.gifContractedSubBlock.gif                {
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
211ExpandedSubBlockStart.gifContractedSubBlock.gif        {
212            get
213ExpandedSubBlockStart.gifContractedSubBlock.gif            {
214                return this._lastName;
215            }

216            set
217ExpandedSubBlockStart.gifContractedSubBlock.gif            {
218                if ((this._lastName != value))
219ExpandedSubBlockStart.gifContractedSubBlock.gif                {
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()
231ExpandedSubBlockStart.gifContractedSubBlock.gif        {
232            return EntityKey.Create(this._fristName, this._lastName);
233        }

234    }

235}

236

 

 

 

 

转载于:https://www.cnblogs.com/liuj/archive/2009/11/04/1595656.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值