属性声明的方式处理事务的解决方案
需求:像wcf一样在方法上面加上属性,那么在此方法里面的执行代码便支持事务
方案
1.方法上需要定义属性
2.判断属性拦截方法
3.如果要拦截方法就需要使用拦截器来调用
上代码:
下面是拦截器代码,使用的是using LinFu.DynamicProxy;动态代理,所以在些方法的时候需要声明virtual
public class Interceptor<T> : IInterceptor
{
private T _target;
private Dictionary<string, Attribute> _methodAttributeCache = new Dictionary<string, Attribute>();
public Interceptor(T target)
{
this._target = target;
foreach (MethodInfo mInfo in typeof(T).GetMethods())
{
foreach (Attribute attr in Attribute.GetCustomAttributes(mInfo))
{
if (attr.GetType() == typeof(OperationBehaviorAttribute))
{
if (!_methodAttributeCache.ContainsValue(attr))
_methodAttributeCache.Add( typeof(T).FullName+"."+ mInfo.Name, attr);
}
}
}
}
public object Intercept(InvocationInfo info)
{
//判断是否有事务属性
var methodFullName = typeof(T).FullName + "." + info.TargetMethod.Name;
if (_methodAttributeCache.ContainsKey(methodFullName))
{
var haverequired = ((OperationBehaviorAttribute)_methodAttributeCache[methodFullName]).TransactionScopeRequired;
if (haverequired)
{
using (TransactionScope tran = new TransactionScope(TransactionScopeOption.Required))
{
var result= info.TargetMethod.Invoke(this._target, info.Arguments);
tran.Complete();
return result;
}
}
else
return info.TargetMethod.Invoke(this._target, info.Arguments);
}
else
return info.TargetMethod.Invoke(this._target, info.Arguments);
}
}
下面是调用类,这个类我使用的是单点基类来完成调用的,当然这个单点基类并非真正意义上的单点调用
/// <summary>
/// 单例基类
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonBase<T> where T : class,new()
{
private static T _Instance = null;
private readonly static object _lock = new object();
/// <summary>
/// 单例
/// </summary>
public static T Instance
{
get
{
if (_Instance == null)
{
lock (_lock)
{
if (_Instance == null)
_Instance = new ProxyFactory().CreateProxy<T>(new Interceptor<T>(new T()));
}
}
return _Instance;
}
}
}
类的定义方式
public class UserDAL : SingletonBase<UserDAL>
{
public virtual string Name { get; set; }
public virtual int Age { get; set; }
[OperationBehavior(TransactionScopeRequired=true)]
public virtual string GetName()
{
return "a";
}
}
调用方式
static void Main(string[] args)
{
UserDAL.Instance.GetName();
}