程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> AOP的兩個應用(下)

AOP的兩個應用(下)

編輯:關於C#

AOP的兩個應用:實體集更新(DateEntityListUpdate)、延遲加載(LazyLoad)(下)

LazyLoadableSink類

//*******************************************************************
    // 模塊:實現延遲載入的消息接收器
    // 日期:2009-9-19 14:08:58
    // 作者:Faib
    // 版權:Copyright Faib Studio 2009
    // 官網:http://www.faib.net.cn
    // 郵箱:[email protected]
    // 備注:
    //*******************************************************************
using System;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using FaibClass.Data.Operation;
namespace FaibClass.Data.Aspect
    {
    /// <summary>
    /// 實現延遲載入的消息接收器。
    /// </summary>
    internal class LazyLoadableSink : IMessageSink
    {
    private IMessageSink m_nextSink;
    private MarshalByRefObject m_target;
    private static object syncRoot = new object();
    public LazyLoadableSink(MarshalByRefObject target, IMessageSink nextSink)
    {
    lock (syncRoot)
    {
    m_target = target;
    m_nextSink = nextSink;
    }
    }
    public IMessage SyncProcessMessage(IMessage msg)
    {
    IMethodReturnMessage returnedMessage;
    HandleMessage(msg, false, out returnedMessage);
    return returnedMessage;
    }
    public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
    {
    IMethodReturnMessage returnedMessage;
    HandleMessage(msg, true, out returnedMessage);
    return m_nextSink.AsyncProcessMessage(msg, replySink);
    }
    public IMessageSink NextSink
    {
    get { return m_nextSink; }
    }
    /// <summary>
    /// 處理消息
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="IsAsync"></param>
    /// <param name="returnedMessage"></param>
    private void HandleMessage(IMessage msg, bool IsAsync, out IMethodReturnMessage returnedMessage)
    {
    returnedMessage = null;
    if (!IsAsync)
    {
    if (msg is IMethodCallMessage)
    {
    Type entityType = m_target.GetType();
    IMethodCallMessage mcm = (IMethodCallMessage)msg;
    bool isFill = (bool)entityType.GetProperty("InnerIsFill", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(m_target, null);
    //判斷是否獲取屬性或字段或是調用GetValue方法
    bool isProperty = !isFill && ((mcm.MethodName.Length > 4 &&
    mcm.MethodName.Substring(0, 4) == "get_" && mcm.MethodName != "get_InnerIsFill" &&
    mcm.MethodName != "get_InnerDataState") || mcm.MethodName == "FieldGetter" ||
    mcm.MethodName == "GetValue");
    object oldvalue = null;
    MemberInfo minfo = null;
    //屬性名字段名
    string propertyName = string.Empty;
    if (isProperty)
    {
    //字段
    if (mcm.MethodName == "FieldGetter")
    propertyName = mcm.InArgs[1].ToString();
    //GetValue方法
    else if (mcm.MethodName == "GetValue")
    propertyName = mcm.InArgs[0].ToString();
    //屬性
    else
    propertyName = mcm.MethodName.Replace("get_", "");
    minfo = Utility.GetMember(m_target.GetType(), propertyName);
    if (minfo == null)
    isProperty = false;
    //判斷是否子實體集、引用實體、引用屬性
    else if (!minfo.IsDefined(typeof(SubEntityListAttribute), true) &&
    !minfo.IsDefined(typeof(ReferenceEntityAttribute), true) &&
    !minfo.IsDefined(typeof(ReferencePropertyAttribute), true))
    isProperty = false;
    if (isProperty)
    oldvalue = Utility.GetMemberValue(m_target, minfo, propertyName);
    //值為空時才讀取數據庫
    if (isProperty && oldvalue == null)
    {
    //取出緩存的操作對象
    string key = DataCacheKeyManager.GetEntityInnerData(entityType);
    object innerData = InnerCache<object[]>.Get(key);
    if (innerData != null)
    {
    //構造一下操作對象
    object[] _innerData = (object[])innerData;
    DataHelper data = (DataHelper)Activator.CreateInstance((Type)_innerData[0]);
    if (string.IsNullOrEmpty(data.ConnectionString))
    data.ConnectionString = _innerData[1].ToString();
    OperationArgs operArgs = new OperationArgs(data);
    QueryBuilder query = new QueryBuilder(data.CreateParameters());
    //子實體集
    if (minfo.IsDefined(typeof(SubEntityListAttribute), true))
    {
    SubEntityListAttribute keyAttribute = DataMappingManager.GetSubEntityListKey(entityType, propertyName);
    if (keyAttribute != null)
    {
    IDataEntityList list = (IDataEntityList)Activator.CreateInstance(keyAttribute.EntityListType);
    Type refentityType = list.ModelType;
    //取主鍵值
    object value = ((DataEntity)m_target).GetValue(keyAttribute.PrimaryKey);
    if (value != null)
    {
    //關聯關系
    query.Append(QueryCompare.Equal, keyAttribute.ForeignKey, value);
    if (!string.IsNullOrEmpty(keyAttribute.Condition))
    {
    query.Append(QueryRelation.And, keyAttribute.Condition);
    }
    //查詢實體集
    list = SelectOperator.Select(operArgs, refentityType, query, null, null);
    returnedMessage = new ReturnMessage(list, null, 0, null, mcm);
    ((DataEntity)m_target).SetValue(propertyName, returnedMessage.ReturnValue);
    }
    }
    }
    //引用實體
    else if (minfo.IsDefined(typeof(ReferenceEntityAttribute), true))
    {
    ReferenceEntityAttribute keyAttribute = DataMappingManager.GetReferenceEntityKey(entityType, propertyName);
    //取主鍵值
    object value = ((DataEntity)m_target).GetValue(keyAttribute.ForeignKey);
    if (value != null)
    {
    //關聯關系
    query.Append(QueryCompare.Equal, keyAttribute.PrimaryKey, value);
    object result = GetOperator.Get(operArgs, keyAttribute.ReferenceType, query, null, null);
    returnedMessage = new ReturnMessage(result, null, 0, null, mcm);
    ((DataEntity)m_target).SetValue(propertyName, returnedMessage.ReturnValue);
    }
    }
    //引用屬性
    else if (minfo.IsDefined(typeof(ReferencePropertyAttribute), true))
    {
    ReferencePropertyAttribute keyAttribute = DataMappingManager.GetReferencePropertyKey(entityType, propertyName);
    //取主鍵值
    object value = ((DataEntity)m_target).GetValue(keyAttribute.ForeignKey);
    if (value != null)
    {
    //關聯關系
    query.Append(QueryCompare.Equal, keyAttribute.PrimaryKey, value);
    DataEntity entity1 = GetOperator.Get(operArgs, keyAttribute.ReferenceType, query, null, null);
    if (entity1 != null)
    {
    object result = entity1.GetValue((keyAttribute as ReferencePropertyAttribute).ReferencePropertyName);
    returnedMessage = new ReturnMessage(result, null, 0, null, mcm);
    ((DataEntity)m_target).SetValue((keyAttribute as IKeyAttribute).Property, result);
    }
    }
    }
    data.Dispose();
    }
    }
    }
    }
    if (returnedMessage == null)
    returnedMessage = (IMethodReturnMessage)m_nextSink.SyncProcessMessage(msg);
    }
    else
    {
    returnedMessage = null;
    }
    }
    }
    }

注意,innerData是在實體集加載的時候緩存的一個操作類型及連接串,以便在這裡創建操作實體來進行數據讀取。

遺憾的是,對於Field目前沒有能夠加載出來。

應用這兩個AOP後的模型類沒有太多的改動:

/// <summary>
    /// 公司類別模型類
    /// </summary>
    [Serializable]
    [DataTable("TCompanyType")]
    [LazyLoadable]
    [EntityListUpdatable]
    public class TCompanyType : DataEntity
    {
    
    /// <summary>
    /// 編號
    /// </summary>
    [DataColumn]
    [PrimaryKey(true)]
    public int Id;
    /// <summary>
    /// 名稱
    /// </summary>
    [DataColumn]
    public string Name;
    /// <summary>
    /// 基本類別
    /// </summary>
    [DataColumn]
    public BaseType BaseType;
    /// <summary>
    /// 公司編號
    /// </summary>
    [DataColumn]
    public int CompanyId;
    /// <summary>
    /// 是否已刪
    /// </summary>
    [DataColumn]
    public bool IsDelete;
    /// <summary>
    /// 上級編號
    /// </summary>
    [DataColumn]
    [ForeignKey(OperationTypes.Delete, typeof(TCompanyType), "Id")]
    public int ParentId;
    /// <summary>
    /// 子類個數
    /// </summary>
    [DataColumn]
    public int ChildCount;
    /// <summary>
    /// 排序
    /// </summary>
    [DataColumn]
    public int Sort;
    TCompanies m_Companies = null;
    /// <summary>
    /// 該類別下的所有公司
    /// </summary>
    [SubEntityList(OperationTypes.All, "ID", "CompanyTypeId")]
    public TCompanies Companies
    {
    get
    {
    return m_Companies;
    }
    set { m_Companies = value; }
    }
    TCompanyTypes m_SubCompanyTypes = null;
    /// <summary>
    /// 所有子類別
    /// </summary>
    [SubEntityList(OperationTypes.All, "ID", "ParentId")]
    public TCompanyTypes SubCompanyTypes
    {
    get
    {
    return m_SubCompanyTypes;
    }
    set { m_SubCompanyTypes = value; }
    }
    }

前台調用代碼沒有改變:

private void btnCascadeQuery_Click(object sender, EventArgs e)
    {
    //級聯查詢
    try
    {
    ATCompanyType da = new ATCompanyType();
    da.AccessOptions = AccessOptions.Defined;
    //排除引用實體屬性
    da.PropertyFilter = null;
    //列出分類
    ListSubType(da.Select("ParentId=0"));
    da.Dispose();
    }
    catch (System.Exception e1)
    {
    ShowErrorMessage(e1.Message);
    }
    }
    //列出子分類
    private void ListSubType(TCompanyTypes list)
    {
    if (list == null) return;
    foreach(TCompanyType type in list)
    {
    //分類名稱
    ShowMessage("類別名稱:" + type.Name);
    //該分類下的公司
    ListSubCompany(type.Companies);
    //該分類下的子類
    ListSubType(type.SubCompanyTypes);
    }
    }
    //列出分類公司下面的子公司
    private void ListSubCompany(TCompanies companies)
    {
    if (companies == null) return;
    foreach (TCompany company in companies)
    {
    ShowMessage("公司名稱:" + company.Name);
    ListSubCompany(company.SubCompanies);
    }
    }

總結:使用繼承ContextBoundObject感覺不爽,數據在經過這麼多的Sink後,性能必定有所損耗,但配上分頁,我想這樣的不足可以有所彌補。

聲明:不要死裡的盯著上面的代碼,什麼類不存在,我發這個的目的是闡述裡面思想。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved