AOP的两个应用:实体集更新(DateEntityListUpdate)、延迟加载(LazyLoad)
Posted on 2009-09-20 13:12 faib 阅读(2178) 评论(3) 编辑 收藏 举报
在FaibClass.Data中,有两个AOP的应用,它们分别是实体集更新(DateEntityListUpdate)、延迟加载(LazyLoad),目前的DataEntity继承于ContextBoundObject,刚刚从网上看到ContextBoundObject的损耗非常大,但自己测试了一下,应该说影响不是很大,所以暂时不打算使用静态注入了。
注,两个AOP都采用Attribute--Property--Sink的结构,每个类的具体功能请查阅相关的技术资料。
一、实体集更新(DateEntityListUpdate)
在前台设置一个实体的属性,我们在更新整个实体集到数据库的时候,并不知道哪些属性更改过,如果全部更新,将造成不必要的浪费,所以引入了这个概念。如果我们不这样做,模型类的每个属性set后将添加一句代码AddUpdateColumn。
这里使用了.Net的消息链进行处理,因为实体类上还可能使用了其他的AOP。
EntityListUpdatableAttribute类
EntityListUpdatableProperty类
EntityListUpdatableSink类
二、延迟加载(LazyLoad)
没有仔细研究过其他框架的延迟加载是怎么实现的,自己还是基于.Net的消息机制做了这个功能。
LazyLoadableAttribute类
LazyLoadableProperty类
LazyLoadableSink类
注意,innerData是在实体集加载的时候缓存的一个操作类型及连接串,以便在这里创建操作实体来进行数据读取。
遗憾的是,对于Field目前没有能够加载出来。
应用这两个AOP后的模型类没有太多的改动:
前台调用代码没有改变:
总结:使用继承ContextBoundObject感觉不爽,数据在经过这么多的Sink后,性能必定有所损耗,但配上分页,我想这样的不足可以有所弥补。
声明:不要死里的盯着上面的代码,什么类不存在,我发这个的目的是阐述里面思想。
注,两个AOP都采用Attribute--Property--Sink的结构,每个类的具体功能请查阅相关的技术资料。
一、实体集更新(DateEntityListUpdate)
在前台设置一个实体的属性,我们在更新整个实体集到数据库的时候,并不知道哪些属性更改过,如果全部更新,将造成不必要的浪费,所以引入了这个概念。如果我们不这样做,模型类的每个属性set后将添加一句代码AddUpdateColumn。
这里使用了.Net的消息链进行处理,因为实体类上还可能使用了其他的AOP。
EntityListUpdatableAttribute类
Code
//*******************************************************************
// 模块:指示实体对象可被集合更新
// 日期: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;
}
}
}
//*******************************************************************
// 模块:指示实体对象可被集合更新
// 日期: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类
Code
//*******************************************************************
// 模块:实体集更新的上下文属性
// 日期: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;
}
}
}
//*******************************************************************
// 模块:实体集更新的上下文属性
// 日期: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类
Code
//*******************************************************************
// 模块:用于处理属性修改后的消息接收器
// 日期: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;
}
}
}
}
//*******************************************************************
// 模块:用于处理属性修改后的消息接收器
// 日期: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类
Code
//*******************************************************************
// 模块:延迟加载的属性
// 日期: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;
}
}
}
//*******************************************************************
// 模块:延迟加载的属性
// 日期: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类
Code
//*******************************************************************
// 模块:延迟加载的上下文属性
// 日期: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;
}
}
}
//*******************************************************************
// 模块:延迟加载的上下文属性
// 日期: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;
}
}
}
LazyLoadableSink类
Code
//*******************************************************************
// 模块:实现延迟载入的消息接收器
// 日期:2009-9-19 14:08:58
// 作者:Faib
// 版权:Copyright Faib Studio 2009
// 官网:http://www.faib.net.cn
// 邮箱:faib920@126.com
// 备注:
//*******************************************************************
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;
}
}
}
}
//*******************************************************************
// 模块:实现延迟载入的消息接收器
// 日期:2009-9-19 14:08:58
// 作者:Faib
// 版权:Copyright Faib Studio 2009
// 官网:http://www.faib.net.cn
// 邮箱:faib920@126.com
// 备注:
//*******************************************************************
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后的模型类没有太多的改动:
Code
/// <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; }
}
}
/// <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; }
}
}
前台调用代码没有改变:
Code
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);
}
}
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后,性能必定有所损耗,但配上分页,我想这样的不足可以有所弥补。
声明:不要死里的盯着上面的代码,什么类不存在,我发这个的目的是阐述里面思想。