VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • AOP的两个应用实体集更新DataEntityListUpdate、延迟加载Lazyload(上)

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
  在FaibClass.Data中,有两个AOP的应用,它们分别是实体集更新(DateEntityListUpdate)、延迟加载 (LazyLoad),目前的DataEntity继承于ContextBoundObject,刚刚从网上看到ContextBoundObject的损耗非常大,但自己测试了一下,应该说影响不是很大,所以暂时不打算使用静态注入了。
  注,两个AOP都采用Attribute--Property--Sink的结构,每个类的具体功能请查阅相关的技术资料。
  一、实体集更新(DateEntityListUpdate)
  在前台设置一个实体的属性,我们在更新整个实体集到数据库的时候,并不知道哪些属性更改过,如果全部更新,将造成不必要的浪费,所以引入了这个概念。如果我们不这样做,模型类的每个属性set后将添加一句代码AddUpdateColumn。
  这里使用了.Net的消息链进行处理,因为实体类上还可能使用了其他的AOP。
  EntityListUpdatableAttribute类
//*******************************************************************
// 模块:指示实体对象可被集合更新
// 日期:2009-7-29 1:05
// 作者:Faib
// 版权:Copyright Faib Studio 2009
// 官网:http://www.faib.net.cn
// 邮箱:faib920@126.com
// 备注:
//*******************************************************************
using System;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Activation;
using FaibClass.Data.Aspect;
namespace FaibClass.Data
{
    /// <summary>
    /// 指示实体的属性更改后,可以使用Update更新整个实体集,如果不指定此特性,实体的DataState无法置为Modified。
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
    public class EntityListUpdatableAttribute : Attribute, IContextAttribute, IContextProperty
    {
        internal static string propertyName = "EntityListUpdatable";
        /// <summary>
        /// 构造属性。
        /// </summary>
        public EntityListUpdatableAttribute()
        {
        }
        string IContextProperty.Name
        {
            get { return propertyName; }
        }
        void IContextProperty.Freeze(Context newContext)
        {
        }
        bool IContextProperty.IsNewContextOK(Context newCtx)
        {
            return true;
        }
        void IContextAttribute.GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
        {
            IContextProperty interceptProperty = new EntityListUpdatableProperty();
            ctorMsg.ContextProperties.Add(interceptProperty);
        }
        bool IContextAttribute.IsContextOK(Context ctx, IConstructionCallMessage ctorMsg)
        {
            if (ctx.GetProperty(propertyName) == null)
            {
                return false;
            }
            return true;
        }
    }
}
  EntityListUpdatableProperty类
//*******************************************************************
// 模块:实体集更新的上下文属性
// 日期:2009-9-19 14:24:24
// 作者:Faib
// 版权:Copyright Faib Studio 2009
// 官网:http://www.faib.net.cn
// 邮箱:faib920@126.com
// 备注:
//*******************************************************************
using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;
namespace FaibClass.Data.Aspect
{
    /// <summary>
    /// 实体集更新的上下文属性。
    /// </summary>
    internal class EntityListUpdatableProperty : IContextProperty, IContributeObjectSink
    {
        void IContextProperty.Freeze(Context newContext)
        {
        }
        string IContextProperty.Name
        {
            get { return EntityListUpdatableAttribute.propertyName; }
        }
        bool IContextProperty.IsNewContextOK(Context newCtx)
        {
            EntityListUpdatableProperty property = 
                newCtx.GetProperty(EntityListUpdatableAttribute.propertyName) as EntityListUpdatableProperty;
            if (property == null)
            {
                return false;
            }
            return true;
        }
        IMessageSink IContributeObjectSink.GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
        {
            IMessageSink sink = new EntityListUpdatableSink(obj, nextSink);
            return sink;
        }
    }
}
  EntityListUpdatableSink类
//*******************************************************************
// 模块:用于处理属性修改后的消息接收器
// 日期:2009-9-19 14:24:12
// 作者:Faib
// 版权:Copyright Faib Studio 2009
// 官网:http://www.faib.net.cn
// 邮箱:faib920@126.com
// 备注:
//*******************************************************************
using System;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
namespace FaibClass.Data.Aspect
{
    /// <summary>
    /// 用于处理属性修改后的消息接收器。
    /// </summary>
    internal class EntityListUpdatableSink : IMessageSink
    {
        private IMessageSink m_nextSink;
        private MarshalByRefObject m_target;
        private static object syncRoot = new object();
        public EntityListUpdatableSink(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; }
        }
        private void HandleMessage(IMessage msg, bool IsAsync, out IMethodReturnMessage returnedMessage)
        {
            returnedMessage = null;
            if (!IsAsync)
            {
                if (msg is IMethodCallMessage)
                {
                    IMethodCallMessage mcm = (IMethodCallMessage)msg;
                    bool isFill = (bool)m_target.GetType().GetProperty("InnerIsFill", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(m_target, null);
                    
                    bool isProperty = !isFill && ((mcm.MethodName.Length > 4 &&
                        mcm.MethodName.Substring(0, 4) == "set_" && mcm.MethodName != "set_InnerIsFill" &&
                        mcm.MethodName != "set_InnerDataState" &&
                        mcm.MethodName != "set_InnerData") || mcm.MethodName == "FieldSetter");
                    object oldvalue = null, newvalue = null;
                    MemberInfo minfo = null;
                    string propertyName = string.Empty;
                    //取原来的值
                    if (isProperty)
                    {
                        if (mcm.MethodName == "FieldSetter")
                            propertyName = mcm.InArgs[1].ToString();
                        else
                            propertyName = mcm.MethodName.Replace("set_", "");
                        minfo = Utility.GetMember(m_target.GetType(), propertyName);
                        if (minfo == null)
                            isProperty = false;
                        else if (minfo.IsDefined(typeof(DataColumnAttribute), true))
                            oldvalue = Utility.GetMemberValue(m_target, minfo, propertyName);
                    }
                    returnedMessage = (IMethodReturnMessage)m_nextSink.SyncProcessMessage(msg);
                    
                    if (isProperty)
                    {
                        //新的值
                        newvalue = Utility.GetMemberValue(m_target, minfo, propertyName);
                        if (!newvalue.Equals(oldvalue))
                        {
                            //调用内部方法添加修改了的列
                            m_target.GetType().InvokeMember("AddUpdateColumn", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, m_target, new object[] { mcm.MethodName.Replace("set_", "") });
                        }
                    }
                }
                else
                {
                    returnedMessage = (IMethodReturnMessage)m_nextSink.SyncProcessMessage(msg);
                }
            }
            else
            {
                returnedMessage = null;
            }
        }
    }
}
  二、延迟加载(LazyLoad)
  没有仔细研究过其他框架的延迟加载是怎么实现的,自己还是基于.Net的消息机制做了这个功能。
  LazyLoadableAttribute类
//*******************************************************************
// 模块:延迟加载的属性
// 日期:2009-9-19 14:23:22
// 作者:Faib
// 版权:Copyright Faib Studio 2009
// 官网:http://www.faib.net.cn
// 邮箱:faib920@126.com
// 备注:
//*******************************************************************
using System;
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Activation;
using FaibClass.Data.Aspect;
namespace FaibClass.Data
{
    /// <summary>
    /// 指示该实体中的子实体集、引用实体、引用属性可延迟载入。
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class LazyLoadableAttribute : Attribute, IContextAttribute, IContextProperty
    {
        internal static string propertyName = "LazyLoadable";
     
        /// <summary>
        /// 构造属性。
        /// </summary>
        public LazyLoadableAttribute()
        {
        }
        string IContextProperty.Name
        {
            get { return propertyName; }
        }
        void IContextProperty.Freeze(Context newContext)
        {
        }
        bool IContextProperty.IsNewContextOK(Context newCtx)
        {
            return true;
        }
        void IContextAttribute.GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
        {
            IContextProperty interceptProperty = new LazyLoadableProperty();
            ctorMsg.ContextProperties.Add(interceptProperty);
        }
        bool IContextAttribute.IsContextOK(Context ctx, IConstructionCallMessage ctorMsg)
        {
            if (ctx.GetProperty(propertyName) == null)
            {
                return false;
            }
              
            return true;
        }
    }
}
  LazyLoadableProperty类
//*******************************************************************
// 模块:延迟加载的上下文属性
// 日期:2009-9-19 14:09:46
// 作者:Faib
// 版权:Copyright Faib Studio 2009
// 官网:http://www.faib.net.cn
// 邮箱:faib920@126.com
// 备注:
//*******************************************************************
using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;
namespace FaibClass.Data.Aspect
{
    /// <summary>
    /// 延迟加载的上下文属性。
    /// </summary>
    internal class LazyLoadableProperty : IContextProperty, IContributeObjectSink
    {
        void IContextProperty.Freeze(Context newContext)
        {
        }
        string IContextProperty.Name
        {
            get { return LazyLoadableAttribute.propertyName; }
        }
        bool IContextProperty.IsNewContextOK(Context newCtx)
        {
            LazyLoadableProperty property = 
                newCtx.GetProperty(LazyLoadableAttribute.propertyName) as LazyLoadableProperty;
            if (property == null)
            {
                return false;
            }
            return true;
        }
        IMessageSink IContributeObjectSink.GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
        {
            IMessageSink sink = new LazyLoadableSink(obj, nextSink);
            return sink;
        }
    }
}
  EntityListUpdatableProperty类
//*******************************************************************
// 模块:实体集更新的上下文属性
// 日期:2009-9-19 14:24:24
// 作者:Faib
// 版权:Copyright Faib Studio 2009
// 官网:http://www.faib.net.cn
// 邮箱:faib920@126.com
// 备注:
//*******************************************************************
using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Contexts;
namespace FaibClass.Data.Aspect
{
    /// <summary>
    /// 实体集更新的上下文属性。
    /// </summary>
    internal class EntityListUpdatableProperty : IContextProperty, IContributeObjectSink
    {
        void IContextProperty.Freeze(Context newContext)
        {
        }
        string IContextProperty.Name
        {
            get { return EntityListUpdatableAttribute.propertyName; }
        }
        bool IContextProperty.IsNewContextOK(Context newCtx)
        {
            EntityListUpdatableProperty property = 
                newCtx.GetProperty(EntityListUpdatableAttribute.propertyName) as EntityListUpdatableProperty;
            if (property == null)
            {
                return false;
            }
            return true;
        }
        IMessageSink IContributeObjectSink.GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
        {
            IMessageSink sink = new EntityListUpdatableSink(obj, nextSink);
            return sink;
        }
    }
}
 


相关教程