<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Asp.net MVC 示例項(xiàng)目"Suteki.Shop"分析之---Model和Service

           在Suteki.Shop中Model的原型是基于Linq to SQL創(chuàng)建的,其dbml文件位于Suteki.Shop\Shop.dbml。
      而Suteki.Shop在此文件的基本上,以"partial class "的方式在Suteki.Shop\Model文件夾下創(chuàng)建了相應(yīng)
      的類文件以擴(kuò)展Shop.dbml中Model類的一些方法和屬性聲明,如下圖:

               
           為了便于大家理解,下面以Model中的Product.cs為例進(jìn)行說(shuō)明。
         
           Product是對(duì)網(wǎng)站中所銷售商品的數(shù)據(jù)信息類。在其中定義了一些屬性(聲明在Shop.dbml中):

        private int _ProductId;  //產(chǎn)品ID
        private int _CategoryId;    //產(chǎn)品所屬分類ID
        private string _Name;  //產(chǎn)品名稱
        private string _Description;//產(chǎn)品描述  
        private decimal _Price;  //產(chǎn)品價(jià)格
        private int _Position;  //在列表中的位置
        private int _Weight;  //重量
        private bool _IsActive;  //當(dāng)前是否激活顯示
        private string _UrlName;    //產(chǎn)品的URL鏈接

          

           而Product.cs這個(gè)文件其實(shí)是以partial方式對(duì)Shop.dbml中的Product類的"擴(kuò)展",下面是其實(shí)現(xiàn)代碼:

      public partial class Product : IOrderable, IActivatable, IUrlNamed
      {
          
      partial void OnNameChanging(string value)
          {
              value.Label(
      "Name").IsRequired();
          }

          
      partial void OnNameChanged()
          {
              UrlName 
      = Name.ToUrlFriendly();
          }

          
      partial void OnDescriptionChanging(string value)
          {
              value.Label(
      "Description").IsRequired();
          }

          
      public bool HasMainImage
          {
              
      get
              {
                  
      return this.ProductImages.Count > 0;
              }
          }

          
      public Image MainImage
          {
              
      get
              {
                  
      if (HasMainImage) return this.ProductImages.InOrder().First().Image;
                  
      return null;
              }
          }

          
      public bool HasSize
          {
              
      get
              {
                  
      return this.Sizes.Active().Count() > 0;
              }
          }

          
      public Size DefaultSize
          {
              
      get
              {
                  
      if (this.Sizes.Count() == 0throw new ApplicationException("Product has no default size");
                  
      return this.Sizes[0];
              }
          }

          
      public string IsActiveAsString
          {
              
      get
              {
                  
      if (IsActive) return string.Empty;
                  
      return " Not Active";
              }
          }

       
      public static Product DefaultProduct(int parentCategory, int position)
       {
        
      return new Product 
        {
         ProductId 
      = 0,
         CategoryId 
      = parentCategory,
         Position 
      = position
        };

       }
      }

          
           首先要說(shuō)明的是OnNameChanging方法,該方法的聲明如下(位于Shop.dbml中):     
           

      partial void OnNameChanging(string value);

          
           并且在dbml中相應(yīng)的產(chǎn)品"Name"屬性中對(duì)其進(jìn)行調(diào)用:
        

      [Column(Storage="_Name", DbType="NVarChar(250) NOT NULL", CanBeNull=false)]
          
      public string Name
          {
                  
      get
                  {
                      
      return this._Name;
                  }
                  
      set
                  {
                          
      if ((this._Name != value))
                          {
                              
      this.OnNameChanging(value);
                              
      this.SendPropertyChanging();
                              
      this._Name = value;
                              
      this.SendPropertyChanged("Name");
                              
      this.OnNameChanged();
                          }
                  }
          }

       
           這樣做的目的就是在產(chǎn)品的名稱發(fā)生變更時(shí)調(diào)用該方法以進(jìn)行處理,當(dāng)然該set中還有一些
      其它方法的調(diào)用,這里要不多做說(shuō)明了。下面接著看一下partial類中OnNameChanging方法所做
      的工作:

          partial void OnNameChanging(string value)
          {
              value.Label(
      "Name").IsRequired();
          }


          
           看到這里,如果大家之前看過(guò)我寫(xiě)的這篇文章的話(里面的ValidationProperty類),就會(huì)   
      清楚這里是要對(duì)當(dāng)前傳入的產(chǎn)品名稱變量進(jìn)行“是否為空”的校驗(yàn)了。同理,還有對(duì)產(chǎn)品描述的
      驗(yàn)證規(guī)則:

          partial void OnDescriptionChanging(string value)
          {
              value.Label(
      "Description").IsRequired();
          }  

       
          
           這里要說(shuō)明的一點(diǎn)就是在“數(shù)據(jù)驗(yàn)證”一文中所介紹的“用戶信息驗(yàn)證”與上面所使用的信
      息驗(yàn)證規(guī)則的綁定方式有所不同。即“用戶信息驗(yàn)證”是在相應(yīng)Action中調(diào)用Validate()方法實(shí)
      現(xiàn)的,而上面的這種方式是dbml中以“partial method”方式實(shí)現(xiàn)并在相應(yīng)對(duì)象屬性發(fā)生變化是
      觸發(fā)。

           同樣,在商品的partial類聲明中還包括一些其它的屬性如:HasMainImage,DefaultSize,
      HasSize
      等。
         
            當(dāng)然,如果您在實(shí)際開(kāi)發(fā)中未使用LinqToSql的話,IDE就不會(huì)為您生成相應(yīng)的數(shù)據(jù)實(shí)體類代
      碼,這時(shí)我們可以參考另一個(gè)MVC示例項(xiàng)目“MVCStore”的做法,直接在Model中創(chuàng)建并定義相應(yīng)
      的實(shí)體類,其實(shí)我個(gè)人是比較喜歡MVCStore的那種實(shí)體類結(jié)構(gòu),它Model中數(shù)據(jù)都是只有屬性沒(méi)有
      方法。巧的是MVCStore中也有一個(gè)叫“Product”的Model類,其位于:Commerce.Data\Model\
      Product.cs,大家可以下載其代碼看一下即可。


            除了使用“partial”方式對(duì)Shop.dbml所生成的實(shí)體類代碼進(jìn)行完善擴(kuò)展之外,Suteki.Shop
      項(xiàng)目也采用了大多數(shù)MVC示范中所使用的“Repository”模式對(duì)Model中類的CRUD方法進(jìn)行封裝,
      只不過(guò)它做的更“高明”一些,即使用接口(和泛型接口)方式統(tǒng)一定義了CRUD的名稱,其類圖:

          

            

           注:Suteki.Shop的作者在這篇文章中提到過(guò),這種架構(gòu)方式是吸取了Ayende 這篇文章的思想。而Ayende就是

      Rhino.Commons,Rhino Mocks等軟件作者。

           下面是其相關(guān)的接口聲明:    
         

       public interface IRepository<T> where T : class
          {
              T GetById(
      int id);
              IQueryable
      <T> GetAll();
              
      void InsertOnSubmit(T entity);
              
      void DeleteOnSubmit(T entity);
              [Obsolete(
      "Units of Work should be managed externally to the Repository.")]
              
      void SubmitChanges();
          }

          
      public interface IRepository
          {
              
      object GetById(int id);
              IQueryable GetAll();
              
      void InsertOnSubmit(object entity);
              
      void DeleteOnSubmit(object entity);
              [Obsolete(
      "Units of Work should be managed externally to the Repository.")]
              
      void SubmitChanges();
          }

           
           做為實(shí)現(xiàn)上面兩個(gè)接口的“Repository”類,其承擔(dān)了對(duì)CRUD的具體操作邏輯實(shí)現(xiàn)。   
         

       public class Repository<T> : IRepository<T>, IRepository where T : class
          {
              
      readonly DataContext dataContext;

              
      public Repository(IDataContextProvider dataContextProvider)
              {
                  dataContext 
      = dataContextProvider.DataContext;
              }

              
      public virtual T GetById(int id)
              {
                  var itemParameter 
      = Expression.Parameter(typeof(T), "item");

                  var whereExpression 
      = Expression.Lambda<Func<T, bool>>
                      (
                      Expression.Equal(
                          Expression.Property(
                              itemParameter,
                              
      typeof(T).GetPrimaryKey().Name
                              ),
                          Expression.Constant(id)
                          ),
                      
      new[] { itemParameter }
                      );

                  
      return GetAll().Where(whereExpression).Single();
              }

              
      public virtual IQueryable<T> GetAll()
              {
                  
      return dataContext.GetTable<T>();
              }

              
      public virtual void InsertOnSubmit(T entity)
              {
                  GetTable().InsertOnSubmit(entity);
              }

              
      public virtual void DeleteOnSubmit(T entity)
              {
                  GetTable().DeleteOnSubmit(entity);
              }

              
      public virtual void SubmitChanges()
              {
                  dataContext.SubmitChanges();
              }

              
      public virtual ITable GetTable()
              {
                  
      return dataContext.GetTable<T>();
              }

              IQueryable IRepository.GetAll()
              {
                  
      return GetAll();
              }

              
      void IRepository.InsertOnSubmit(object entity)
              {
                  InsertOnSubmit((T)entity);
              }

              
      void IRepository.DeleteOnSubmit(object entity)
              {
                  DeleteOnSubmit((T)entity);
              }

              
      object IRepository.GetById(int id)
              {
                  
      return GetById(id);
              }
          }

          
           在上面的類圖中,還有兩個(gè)類也很重要,其中IRepositoryResolver是一個(gè)分析器接口,其定義了
      “傳入一個(gè)type類型并在Castle容器中獲取該type組件實(shí)例的方法聲明”,而作為其接口具體實(shí)現(xiàn),
      RepositoryResolver”的實(shí)現(xiàn)代碼如下:
         

       public class RepositoryResolver : IRepositoryResolver
          {
              
      private readonly IKernel kernel;

              
      public RepositoryResolver(IKernel kernel)
              {
                  
      this.kernel = kernel;
              }

              
      public IRepository<T> GetRepository<T>() where T : class 
              {
                  Type repositoryType 
      = typeof(IRepository<>).MakeGenericType(new[] { typeof(T) });

                  var repository 
      = kernel.Resolve(repositoryType) as IRepository<T>;
                  
      if (repository == null)
                  {
                      
      throw new ApplicationException(StringExtensions.With("Could not find IRepository<{0}> in kernel"typeof(T).Name));
                  }
                  
      return repository;
              }

              
      public IRepository GetRepository(Type type)
              {
                  Type repositoryType 
      = typeof(IRepository<>).MakeGenericType(new[] { type });

                  var repository 
      = kernel.Resolve(repositoryType);
                  
                  
      if (repository == null)
                  {
                      
      throw new ApplicationException("Could not find IRepository<{0}> in kernel".With(type.Name));
                  }

                  
      if ((repository as IRepository) == null)
                  {
                      
      throw new ApplicationException("The repository that implements IRepository<{0}> does not implement IRepository".With(type.Name));
                  }

                  
      return (IRepository)repository;
              }
          }

         

           上面的部分代碼涉及到了castle框架的核心功能,可以參見(jiàn)我寫(xiě)的這篇文章即可。大家只要
      知道其實(shí)現(xiàn)的與我們以前“使用反射方式動(dòng)態(tài)生成相應(yīng)類實(shí)例”的目的相同就行了。

           通過(guò)上面這幾個(gè)類,我們?yōu)镸odel中的類提供了“CRUD”方法,這要比之前我所看到的一些
      MVC示例相應(yīng)中的Repository模式實(shí)現(xiàn)的要好一些。當(dāng)然我猜測(cè)這種實(shí)現(xiàn)也是有性能問(wèn)題的,比
      如說(shuō)對(duì)反射的使用,希望借助castle框架能將這個(gè)問(wèn)題化解。

           有了“Repository”類的幫助,讓“Repositories”下的文件夾中的文件少了許多,當(dāng)然上
      面的接口方法未必就能把所有的CRUD操作全部覆蓋,比如Product就需要有這樣一個(gè)功能,即按
      “商品所屬分類”來(lái)獲取同一類下的所有商品。而這個(gè)功能的實(shí)現(xiàn)最終還是要在Repositories
      文件夾下創(chuàng)建一個(gè)類,名為“ProductRepositoryExtensions”:

      public static class ProductRepositoryExtensions
      {
          
      public static IQueryable<Product> WhereCategoryIdIs(this IQueryable<Product> products, int categoryId)
          {
              
      return products.Where(p => p.CategoryId == categoryId);
          }
      }


           但這已經(jīng)是比“實(shí)現(xiàn)所有的CRUD方法的代碼”那種情況下的行數(shù)少了許多了。
         
         
           有了這種實(shí)現(xiàn)方式之后,就可以在Controller中定義相應(yīng)的Model Repository實(shí)例了,其
      行如(Suteki.Shop\Controllers\ProductController.cs):

      public class ProductController : ControllerBase
      {
           
      readonly IRepository<Product> productRepository;
           
      readonly IRepository<Category> categoryRepository;
                     
      }


              
           看到這里,大家應(yīng)該基本搞清楚該項(xiàng)目中Model和相關(guān)的CRUD方法的實(shí)現(xiàn)原理了。下面接著再介
      紹一下項(xiàng)目中Services的實(shí)現(xiàn)。

           首先,可以說(shuō)其所有Service都有相關(guān)的接口進(jìn)行定義。

           以UserService類為例(Suteki.Shop\Services\UserService.cs),其實(shí)現(xiàn)了“IUserService”
      接口,如下: 

      public interface IUserService
      {
              User CreateNewCustomer();
              User CurrentUser { 
      get; }
              
      void SetAuthenticationCookie(string email);
              
      void SetContextUserTo(User user);
              
      void RemoveAuthenticationCookie();
              
      string HashPassword(string password);
              
      bool Authenticate(string email, string password);
      }


          
           這樣做的原因相信大家都清楚, 就是將來(lái)如果業(yè)務(wù)規(guī)則變化時(shí)(對(duì)應(yīng)service接口實(shí)現(xiàn)類也要發(fā)
      生變化),這時(shí)不需要真正修改已有的代碼,只需再開(kāi)發(fā)一個(gè)相應(yīng)的實(shí)現(xiàn)類即可滿足需求,這種擴(kuò)展
      方式也是與設(shè)計(jì)模式中的思想相符合的。除此之外,我再談一下我對(duì)該項(xiàng)目中Service實(shí)現(xiàn)的一些個(gè)
      人觀點(diǎn):    
           Suteki.Shop對(duì)于其Service的封裝我認(rèn)為并不好,原因就在于“Model中是否應(yīng)該包括業(yè)務(wù)邏輯”
      這個(gè)問(wèn)題上,我本人感覺(jué)對(duì)于小項(xiàng)目而言(Suteki.Shop,MVCStore就是這樣的小項(xiàng)目),還真談不
      上什么充血模型。能把一個(gè)貧血模型實(shí)現(xiàn)并用好了就完全可以了。而Suteki.Shop中的Model中過(guò)多的
      注入了方法代碼,其中有些應(yīng)該是放在Service中。

           這一點(diǎn)我是強(qiáng)烈建議參考MVCStore下的“Commerce.Services”這個(gè)項(xiàng)目的實(shí)現(xiàn),其實(shí)現(xiàn)的方式
      我感覺(jué)非常符合當(dāng)下SOA倡導(dǎo)的架構(gòu)方式。有關(guān)這方面的內(nèi)容我在這篇文章中就已闡述,就不
      做說(shuō)明了。

           
           好了,今天的內(nèi)容就先到這里了。    
          
           原文鏈接: http://www.rzrgm.cn/daizhj/archive/2009/05/31/1455867.html

           作者: daizhj,代震軍,LaoD

           Tags: mvc,Suteki.Shop

           網(wǎng)址: http://daizhj.cnblogs.com/ 
       
         
         
         
       

      posted @ 2009-05-31 09:01  代震軍  閱讀(8091)  評(píng)論(14)    收藏  舉報(bào)
      主站蜘蛛池模板: 午夜精品极品粉嫩国产尤物| 噜噜综合亚洲av中文无码| 狠狠色噜噜狠狠狠狠色综合久| 免费无码又爽又刺激网站直播| 中文字幕国产日韩精品| 怀远县| 久久国产成人午夜av影院| 午夜福利精品国产二区| 一区二区三区AV波多野结衣| 久久精品娱乐亚洲领先| 天堂mv在线mv免费mv香蕉| 成av免费大片黄在线观看| 亚洲欧美色综合影院| 国产亚洲精品精品精品| 精品国偷自产在线视频99| 青青草无码免费一二三区| 国产卡一卡二卡三免费入口| 久久96国产精品久久久| 国产福利酱国产一区二区| 久久这里有精品国产电影网| 国产精品中文字幕免费| 亚洲第一区二区国产精品| 天天躁日日躁狠狠躁av麻豆男男| 亚洲人成网站在线观看播放不卡| 亚洲高清国产拍精品熟女| 国产亚洲中文字幕久久网| 五月天天天综合精品无码| 久久久亚洲欧洲日产国码αv| 亚洲欧洲精品一区二区| bt天堂新版中文在线| 精品国产成人亚洲午夜福利| 新婚少妇无套内谢国语播放| 国产啪视频免费观看视频| 男女xx00xx的视频免费观看| 国产精品99久久久久久www| 撕开奶罩揉吮奶头高潮AV| 中文在线天堂中文在线天堂| 露脸一二三区国语对白| 男女啪啪高潮激烈免费版| 丁香婷婷色综合激情五月| 精品人妻二区中文字幕|