Closed 2881099 closed 2 years ago
目的只发现这一个容易掉坑的问题,如果能解决就完美了。
MoAttribute
的生命周期对应被织入方法的生命周期,对于你描述的这种情况,是符合预期设定的。当然你遇到的这种场景,可以通过MethodContext.RealReturnType
判断返回值是否为Task
,然后通过ContinueWith
的方式在Task
结束时执行OnExit
逻辑。
以你文档中的TransactionalAttribute
为例:
[AttributeUsage(AttributeTargets.Method)]
public class TransactionalAttribute : Rougamo.MoAttribute
{
// ...
public override void OnExit(MethodContext context)
{
if (typeof(Task).IsAssignableFrom(context.RealReturnType))
{
((Task)context.ReturnValue).ContinueWith(t => _OnExit());
}
else
{
_OnExit();
}
void _OnExit()
{
try
{
if (context.Exception == null) _uow.Commit();
else _uow.Rollback();
}
finally
{
_uow.Dispose();
}
}
}
}
补充说明一下,MethodContext.RealReturnType
对于Task/Task<T>
返回值但没有async
语法的,其值就是Task/Task<T>
本身,而如果使用了async
语法,那么Task
将对应typeof(void)
,Task<T>
将对应typeof(T)
感谢,明白了。建议在首页特别说明一下
代码应该是 context.ReturnValue = ...
好的,我后续将这种情况记录到REAMDE中。
如果你希望替换返回值,请使用context.ReplaceReturnValue(this, returnValue)
,直接通过context.ReturnValue
设置返回值会跳过一些逻辑,这些逻辑在不同版本可能还会不一样。
对了,还有一点,context.ReplaceReturnValue(this, returnValue)
只能在OnEntry
和OnSuccess
中使用,OnExit
中无法修改返回值
这就矛盾了啊,因为上面你给的代码需要获取 context.ReturnValue,这个在 OnEntry 获取不到吧。
在OnExit
中可以获取返回值,但是不能修改。
在OnEntry
中应该叫设置返回值,应用场景比如异常参数检查返回固定返回值和缓存直接返回。
好的,先解决 Task async,谢谢
https://github.com/dotnetcore/FreeSql/wiki/DI-UnitOfWorkManager 谢谢,文档已更新,全面替换 castle.core
不客气,你们知名的开源项目愿意使用这样一个起步不久的项目,是我的荣幸,感谢使用
本来只提供 UnitOfWorkManager 功能,就缺个动态代理。
之前一直没有推荐动态代理类库,他们比较喜欢 castle.core,整理出来的文档看起来太复杂 https://freesql.net/extra/aop-freesql-autofac.html
肉夹馍关注有一段时间了,今天试了一下太好用了,没有理由不推荐给大家。
刚发布了1.2.0版本,新增了ExMoAttribute
,这个Attribute对有async语法和没有async语法的方法采用一致的生命周期,这个可能对你有用,TransactionalAttribute
可以改成下面这样:
[AttributeUsage(AttributeTargets.Method)]
public class TransactionalAttribute : Rougamo.ExMoAttribute
{
// ...
public override void ExOnExit(MethodContext context)
{
try
{
if (context.Exception == null) _uow.Commit();
else _uow.Rollback();
}
finally
{
_uow.Dispose();
}
}
}
还有一点提醒一下,OnExit/ExOnExit
中通过MethodContext.Exception == null
来判断方法是否抛出异常并不完全准确,如果在OnException/ExOnException
中通过MethodContext.HandledException
方法处理掉异常,那么OnExit/ExOnExit
中MethodContext.Exception
就会返回null,如果希望在异常被处理的情况下依旧Rollback,可以将判断条件改为if (context.Exception == null) && !context.ExceptionHandled)
谢谢提醒,上面够用了,非常好用
感觉作者提供这么方便的组件。
上面 InsertTest 方法没有标记 async,当进入 OnExit 的时候会清除 _repo.UnitOfWork 状态,但是 _repo.InsertAsync 插入并未完成。不知道是否存在这种执行顺序问题?