日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
NHibernate2.1新特性之Tuplizers

Tuplizers?這個(gè)單詞在英文字典里沒(méi)有解釋,和元組(tuple)這個(gè)單詞有點(diǎn)相似,在NHibernate中應(yīng)該翻譯為元組片斷,Tuplizers只在映射中提供,所以叫元組片段映射比較合適。

成都創(chuàng)新互聯(lián)專注于臨朐企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,成都商城網(wǎng)站開(kāi)發(fā)。臨朐網(wǎng)站建設(shè)公司,為臨朐等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站策劃,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

我們平時(shí)一般使用Domain Entity,然后使用< class>來(lái)映射,對(duì)Domain Entity操作。在NHibernate中,對(duì)于Domain Entity的Entity Mode為POCO類型,這時(shí)對(duì)應(yīng)的tuplizer知道通過(guò)其構(gòu)造方法來(lái)創(chuàng)建一個(gè)POCO,再通過(guò)其屬性訪問(wèn)器來(lái)訪問(wèn)POCO屬性。

Tuplizers,其完整命名空間是NHibernate.Tuple.Tuplizer,它就是根據(jù)給定的NHibernate.EntityMode,來(lái)復(fù)現(xiàn)片斷數(shù)據(jù)。如果給定的片斷數(shù)據(jù)被認(rèn)為其是一種數(shù)據(jù)結(jié)構(gòu),"tuplizer"就是一個(gè)知道如何創(chuàng)建這樣的數(shù)據(jù)結(jié)構(gòu),以及如何給這個(gè)數(shù)據(jù)結(jié)構(gòu)賦值的東西。

在NHibernate中有NHibernate.Tuple.Entity.IEntityTuplizer和NHibernate.Tuple.Component.IComponentTuplizer兩個(gè)接口,IEntityTuplizer負(fù)責(zé)管理上面提到的實(shí)體的契約,而IComponentTuplizer則是針對(duì)組件的。

下面從NHibernate源碼中摘取一個(gè)典型的例子來(lái)說(shuō)明Tuplizer的用法。

典型實(shí)例

我想映射一個(gè)接口,對(duì)這個(gè)接口按照POCO實(shí)體模型進(jìn)行持久化操作。首先想到應(yīng)該可以New出來(lái)這個(gè)接口,使用工廠可以產(chǎn)生出來(lái)。在初始化這個(gè)接口的時(shí)候要重寫一些NHibernate默認(rèn)的POCO行為,在對(duì)這個(gè)接口賦值的時(shí)候攔截一些操作,記錄下這個(gè)接口。獲取接口時(shí)候同樣也需要攔截。

1.Domain

 
 
 
  1. public interface IUser
  2. {
  3.     int Id { get; set; }
  4.     string Name { get; set; }
  5. }

我們需要映射這個(gè)接口,但是NHibernate只會(huì)去映射類,我們?cè)趺慈ジ膶懘a讓NHibernate可以像類那樣去映射接口呢?這就是Tuplizers的功能。

2.代理標(biāo)記proxy marker

由于這里是特殊需要,我對(duì)其這個(gè)代理做個(gè)標(biāo)記,如果某個(gè)實(shí)體可以轉(zhuǎn)換為這個(gè)代理標(biāo)記接口就說(shuō)明是我重寫定義的Domain,

 
 
 
  1. /// < summary>
  2. /// 代理標(biāo)記
  3. /// 對(duì)象實(shí)例是代理的一個(gè)實(shí)例
  4. /// < /summary>
  5. public interface IProxyMarker
  6. {
  7.     DataProxyHandler DataHandler { get; }
  8. }

3.DataProxy

利用Castle的攔截器IInterceptor接口對(duì)這個(gè)代理數(shù)據(jù)進(jìn)行攔截,例如在獲取這個(gè)代理數(shù)據(jù)的時(shí)候,讓NHibernate按照POCO那樣去把其數(shù)據(jù)保存到一個(gè)字典中。

 
 
 
  1. /// < summary>
  2. /// 利用Castle的攔截器,代理數(shù)據(jù)DataProxy
  3. /// < /summary>
  4. public sealed class DataProxyHandler:IInterceptor
  5. {
  6.     private readonly Dictionary< stringobject> data = new Dictionary< stringobject>(50);
  7.     private readonly string entityName;
  8.     public DataProxyHandler(string entityName, object id)
  9.     {
  10.         this.entityName = entityName;
  11.         data["Id"] = id;
  12.     }
  13.     public string EntityName
  14.     {
  15.         get { return entityName; }
  16.     }
  17.     public IDictionary< stringobject> Data
  18.     {
  19.         get { return data; }
  20.     }
  21.     public void Intercept(IInvocation invocation)
  22.     {
  23.         invocation.ReturnValue = null;
  24.         string methodName = invocation.Method.Name;
  25.         if ("get_DataHandler".Equals(methodName))
  26.         {
  27.             invocation.ReturnValue = this;
  28.         }
  29.         else if (methodName.StartsWith("set_"))
  30.         {
  31.             string propertyName = methodName.Substring(4);
  32.             data[propertyName] = invocation.Arguments[0];
  33.         }
  34.         else if (methodName.StartsWith("get_"))
  35.         {
  36.             string propertyName = methodName.Substring(4);
  37.             object value;
  38.             data.TryGetValue(propertyName, out value);
  39.             invocation.ReturnValue = value;
  40.         }
  41.         else if ("ToString".Equals(methodName))
  42.         {
  43.             invocation.ReturnValue = EntityName + "#" + data["Id"];
  44.         }
  45.         else if ("GetHashCode".Equals(methodName))
  46.         {
  47.             invocation.ReturnValue = GetHashCode();
  48.         } 
  49.     }
  50. }

4.實(shí)體初始化

在映射文件中定義< tuplizers>映射,NHibernate提供的IInstantiator接口實(shí)現(xiàn)負(fù)責(zé)初始化實(shí)體實(shí)例,這里就是使用Castle.DynamicProxy.ProxyGenerator的public object CreateInterfaceProxyWithoutTarget(System.Type interfaceToProxy, System.Type[] additionalInterfacesToProxy, params Castle.Core.Interceptor.IInterceptor[] interceptors )方法創(chuàng)建一個(gè)接口代理。

 
 
 
  1. /// < summary>
  2. /// 利用NH2.1新特性Tuplizers提供的IInstantiator接口實(shí)現(xiàn)負(fù)責(zé)初始化實(shí)體/組件實(shí)例
  3. /// < /summary>
  4. public class EntityInstantiator : IInstantiator
  5. {
  6.     private static readonly ProxyGenerator proxyGenerator = new ProxyGenerator();
  7.     private readonly Type t;
  8.     public EntityInstantiator(Type entityType)
  9.     {
  10.         t = entityType;
  11.     }
  12.     public object Instantiate()
  13.     {
  14.         return Instantiate(null);
  15.     }
  16.     public object Instantiate(object id)
  17.     {
  18.         return
  19.             proxyGenerator.CreateInterfaceProxyWithoutTarget(t, new[] { typeof(IProxyMarker), t }, new DataProxyHandler(t.FullName, id));
  20.     }
  21.     /// < summary>
  22.     /// 判斷是否實(shí)例化
  23.     /// < /summary>
  24.     /// < param name="obj">< /param>
  25.     /// < returns>< /returns>
  26.     public bool IsInstance(object obj)
  27.     {
  28.         try
  29.         {
  30.             return t.IsInstanceOfType(obj);
  31.         }
  32.         catch (Exception e)
  33.         {
  34.             throw new Exception("could not get handle to entity-name as interface : " + e);
  35.         }
  36.     }
  37. }

5.重寫PocoEntityTuplizer

這才是我們真正自定義的Tuplizer,在映射中使用,重寫NHibernate提供的POCO的PocoEntityTuplizer的初始化方法,返回上面實(shí)體初始化類完成的創(chuàng)建一個(gè)接口代理。

 
 
 
  1. /// < summary>
  2. /// 重寫PocoEntityTuplizer
  3. /// < /summary>
  4. public class EntityTuplizer : PocoEntityTuplizer
  5. {
  6.     public EntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) : base(entityMetamodel, mappedEntity) { }
  7.     protected override IInstantiator BuildInstantiator(PersistentClass persistentClass)
  8.     {
  9.         return new EntityInstantiator(persistentClass.MappedClass);
  10.     }
  11. }

6.實(shí)體攔截

NHibernate可以利用NHibernate.IInterceptor實(shí)現(xiàn)攔截這個(gè)實(shí)體:可以去攔截我們創(chuàng)建一個(gè)System.Type代理將出現(xiàn)無(wú)法預(yù)測(cè)的值,在這里我僅僅返回上面定義的IProxyMarker標(biāo)記數(shù)據(jù)的實(shí)體名稱,對(duì)于其他類型的實(shí)體則返回空值。

 
 
 
  1. /// < summary>
  2. /// 利用NHibernate.IInterceptor對(duì)這個(gè)實(shí)體實(shí)現(xiàn)攔截
  3. /// < /summary>
  4. public class EntityNameInterceptor : EmptyInterceptor
  5. {
  6.     public override string GetEntityName(object entity)
  7.     {
  8.         return ExtractEntityName(entity) ?? base.GetEntityName(entity);
  9.     }
  10.     private static string ExtractEntityName(object entity)
  11.     {
  12.         // Our custom Proxy instances actually bundle their appropriate entity name, 
  13.         //so we simply extract it from there if this represents one of our proxies; otherwise, we return null 
  14.         var pm = entity as IProxyMarker;
  15.         if (pm != null)
  16.         {
  17.             var myHandler = pm.DataHandler;
  18.             return myHandler.EntityName;
  19.         }
  20.         return null;
  21.     } 
  22. }

7.EntityFactory

我們創(chuàng)建一個(gè)實(shí)體工廠,所謂工廠就是New出來(lái)實(shí)體的一個(gè)制造工廠。我們可以var user = entityFactory.NewEntity< IUser>()這樣初始化一個(gè)實(shí)體。

 
 
 
  1. public class EntityFactory
  2. {
  3.     private static readonly ProxyGenerator proxyGenerator = new ProxyGenerator();
  4.     public T NewEntity< T>()
  5.     {
  6.         Type t = typeof(T);
  7.         return
  8.             (T)
  9.             proxyGenerator.CreateInterfaceProxyWithoutTarget(t, new[] { typeof(IProxyMarker), t },
  10.                                                              new DataProxyHandler(t.FullName, 0));
  11.     }
  12. }

上面那些部分相當(dāng)于一個(gè)前奏,為使用tuplizer做準(zhǔn)備,我們可以在映射中使用我們自定義的Tuplizer了。

8.映射

這時(shí)需要映射這個(gè)接口了,使用< tuplizer>映射,這個(gè)映射有兩個(gè)屬性,分別為class和entity-mode。在這個(gè)例子中我在IUser中按照POCO實(shí)體模型自定義EntityTuplizer實(shí)現(xiàn)來(lái)映射。

 
 
 
  1. < class name="IUser">
  2.     < tuplizer class="EntityTuplizer" entity-mode="poco"/>
  3.     < id name="Id">
  4.         < generator class="hilo"/>
  5.     < /id>
  6.     < property name="Name"/>
  7. < /class>

9.測(cè)試

測(cè)試一下我們的結(jié)果吧。分別創(chuàng)建、查詢、刪除操作吧。

[Test]

 
 
 
  1. public void UserCrud()
  2. {
  3.     object savedId;
  4.     var user = entityFactory.NewEntity< IUser>();
  5.     user.Name = "李永京";
  6.     using (var session = sessions.OpenSession())
  7.     using (var tx = session.BeginTransaction())
  8.     {
  9.         savedId = session.Save(user);
  10.         tx.Commit();
  11.     }
  12.     using (var session = sessions.OpenSession())
  13.     using (var tx = session.BeginTransaction())
  14.     {
  15.         user = session.Get< IUser>(savedId);
  16.         Assert.That(user, Is.Not.Null);
  17.         Assert.That(user.Name, Is.EqualTo("李永京"));
  18.         session.Delete(user);
  19.         tx.Commit();
  20.     }
  21.     using (var session = sessions.OpenSession())
  22.     using (var tx = session.BeginTransaction())
  23.     {
  24.         user = session.Get< IUser>(savedId);
  25.         Assert.That(user, Is.Null);
  26.         tx.Commit();
  27.     }
  28. }
  29.  

結(jié)語(yǔ)

由于NHibernate資料很少,所以我從源碼中找到這個(gè)例子稍微說(shuō)明下,大家對(duì)Tuplizer有什么好的想法可以回復(fù)討論下咯,我想這個(gè)功能的擴(kuò)展就是如果NHibernate Domain與WPF結(jié)合,我需要在所有Domain中實(shí)現(xiàn)INotifyPropertyChanged接口,就需要重新實(shí)現(xiàn)DataProxyHandler。


當(dāng)前標(biāo)題:NHibernate2.1新特性之Tuplizers
文章網(wǎng)址:http://www.dlmjj.cn/article/dhddsjo.html