ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

边界切面和方法拦截学习,C#事务和线程安全

2019-08-16 10:03:12  阅读:210  来源: 互联网

标签:边界 C# args 线程 切面 拦截 方法


趁着这几天有时间摸鱼的功夫,赶紧再更新一次博客,将学习到的知识记录下来

1.边界切面

常规意义上讲,边界就是用于区分两种东西的标识,它可以是线、皮毛或是物种等。
编码中的边界其实也是一样的,从主函数main中调用另一个方法时,两个方法之间便会穿过一个边界,该边界在未使用时便是透明的。我们可以通过边界控制方法执行前、执行后的结果,减少方法之间的耦合或增加一些复用性很高的代码。

切面实现

此次切面实现使用的是 PostSharp 组件,该组件提供了边界切面和方法拦截的实现接口。
PostSharp可以在vs自带的nuGet包里搜索下载。
下载完成后在类中进行引用:
using PostSharp.Aspects;
负责边界拦截的类一定要 继承OnMethodBoundaryAspect接口 并实现 OnEntry(执行方法前)OnSuccess(执行方法后) 两个类就可以了;注意:必须要在类上加 Serializable特性,因为组件在实现边界切面会序列化,编译完成后在反序列化:

    [Serializable]
    public class Class1: MethodInterceptionAspect
    {
    	public override void OnEntry(MethodExecutionArgs args)
    	{
    		//方法执行前
    		...
    	}
    	public override void OnSuccess(MethodExecutionArgs args)
    	{
			//方法执行后
			...
		}
    }

可通过MethodExecutionArgs对象获取进入边界切面的方法的实参、方法名称等属性,具体上下文可以在网上找,这里就不一一列出来了。

2.方法拦截

方法拦截其实就是代替被拦截的方法执行一段高可用、高复用的代码,但是 方法拦截非特殊情况下不能完全代替被执行的方法

方法拦截实现

此次的方法拦截也是用PortSharp组件实现,会简单一些。
同边界切面一样,先添加PortSharp引用:
using PostSharp.Aspects;
随后继承的接口变更为 MethodIntercePtionAspect 接口并重写实现OnInvoke方法,注意:必须要在类上加 Serializable特性,因为组件在实现边界切面会序列化,编译完成后在反序列化:

		[Serializable]
        public class Class1: MethodInterceptionAspect
        {
        	public override void OnInvoke(MethodInterceptionArgs args)
        	{
        		//拦截方法时需要实现的代码段
        		...
        	}
		}

和边界一样,通过MethodInterceptionArgs对象可以获得拦截方法的实参、方法名称等属性,上下文一样可在网上查。

边界切面和方法拦截对比

先上图:
在这里插入图片描述
两者并没有太大区别,从上图可以看到:边界切面和方法拦截相差不多,略微改动就可以进行转换。所以我们在应用时,只需要按情况进行变更即可。也有专一的使用同一个切面的。
边界切面由于是多个方法执行,所以变量是不共享的,需要使用 MethodExecutionTag 设置变量传递。也可以使用全局变量,但每个全局变量只有在实例化的时候才会更新(一个方法进入切面后会更新一次全局变量,同一个方法进入多次不会更新 ),由于全局变量不是线程安全的,所以在编写的切面使用了复杂的共享数据,或者使用了很多共享数据,使用方法拦截是较好的选择(单一实现方法)。
如果共享数据简单、较少或者方法需要执行一些独立的边界时,使用边界切面是较好的方法。

3.UI线程安全,C#事务
UI线程安全

每个Form控件都有一个主线程,当我们用另外一个现场控制控件时会抛出线程安全异常。之前使用的方法时线程回调,复杂度较高;在学习边界切面时发现另一个简单好用的线程回调,写出来分享一下。
只需要通过主UI线程的InvokeRequired获得当前线程是否为主线程,返回 true 则说明是主线程,这时需要通过基类的Action进行回调即可:

			//切面写法
            var from = args.Instance as Form1;
            if (from.InvokeRequired)
            {
                from.Invoke(new Action(args.Proceed));
            }
            else
            {
                args.Proceed();
            }
            //Form类写法
            if(InvokeRequired)
            {
            	Invoke(new Action(回调的方法))
            }
            else
            {
				直接执行方法
			}
事务

添加vs的Transactions库,在类中增加它的调用:

using System.Transactions;

该库实现了IDisposible,建议使用using,因为没有使用complete提交前释放对象就会事务回滚。
所以只需要

using (var ts = new TransactionScope())
{
	//进行数据操作
	...
	//有异常则无法提交,会进行事务回滚
    //提交
    ts.Complete();
}

该事务方法较简单,可以快速上手,所以与大家分享一下。

一个接触编程1.5年的白同学

标签:边界,C#,args,线程,切面,拦截,方法
来源: https://blog.csdn.net/weixin_41528552/article/details/99635443

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有