有一个窗体,上面有三个按钮,现在我们需要对其进行权限控制,控制哪些按钮可以操作,哪些不可以操作,而且当权限控制发生改变时不会去修改代码,只需要简单修改配置即可。
首先我们建一个工程,名字随个人喜好啦,(由于本人使用的机器是装的VS2005英文版,所以Demo也是用它完成的,其中可能有些文件的组织方式是按照VS2005来的,不过也没关系,只要把partial类的内容合并了就可以放在2003下面用了)
配置文件内容如下:
1
<configuration>
2
<configSections>
3
<!--用来配置权限的配置节-->
4
<section name="PopedomControlList" type="System.Configuration.DictionarySectionHandler"/>
5
</configSections>
6![](/Images/OutliningIndicators/None.gif)
7
<!--控制信息,这里控制了按钮的访问权限-->
8
<PopedomControlList>
9
<add key="btnOne" value="true"/>
10
<add key="btnTwo" value="true"/>
11
<add key="btnThree" value="false"/>
12
</PopedomControlList>
13
14
</configuration>
配置文件中配置了我对3个按钮的访问权限,true为可以访问,false不能访问。
OK,我们再在工程中添加对Castle.DynamicProxy.dll的引用,然后就可以开始写代码了。
设计好窗体(这里就不再详细说明了),然后创建一个拦截器:
1![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//******************************
2
* 作者:米小波
3
* 日期:2005-12-05
4
* ****************************/
5
6![](/Images/OutliningIndicators/None.gif)
7
using System;
8
using System.Collections.Generic;
9
using System.Text;
10
using System.Windows.Forms;
11![](/Images/OutliningIndicators/None.gif)
12
using Castle.DynamicProxy;
13![](/Images/OutliningIndicators/None.gif)
14
namespace PopedomDemo
15![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
16![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
17
/// 实现方法调用拦截处理
18
/// </summary>
19
public class MyInterceptor : StandardInterceptor
20![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
21![](/Images/OutliningIndicators/InBlock.gif)
22![](/Images/OutliningIndicators/ContractedSubBlock.gif)
IInterceptor Members#region IInterceptor Members
23
public override object Intercept(IInvocation invocation, params object[] args)
24![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
25
//判断并只处理按钮事件
26
if (args.Length > 0)
27![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
28
Button btn = args[0] as Button;
29
if (btn != null)
30![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
31
string btnName = btn.Name;
32
if (Program.PopedomList.Contains(btnName))
33![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
34
if (Check(btnName))
35![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
36
return invocation.Proceed(args);
37
}
38
return null;
39
}
40
}
41
}
42
return base.Intercept(invocation, args);
43
}
44![](/Images/OutliningIndicators/InBlock.gif)
45
46
#endregion
47![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
48
/// 检查按钮权限
49
/// </summary>
50
/// <param name="btnName"></param>
51
/// <returns></returns>
52
private bool Check(string btnName)
53![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
54
if (Program.PopedomList[btnName] != null)
55![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
56
if (Program.PopedomList[btnName].ToString().ToLower() == "true")
57![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
58
return true;
59
}
60
}
61
return false;
62
}
63
}
64
}
65![](/Images/OutliningIndicators/None.gif)
上面代码中,我们重载了StandardInterceptor的Intercept方法,这个是拦截器必须实现的IInterceptor中的方法,StandardInterceptor实现了IInterceptor的该方法,并且在其中使用了模板方法模式,
1
namespace Castle.DynamicProxy
2![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
3
using System;
4![](/Images/OutliningIndicators/InBlock.gif)
5
[Serializable]
6
public class StandardInterceptor : IInterceptor
7![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
8![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public StandardInterceptor()
{ }
9![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
protected virtual void PreProceed(IInvocation invocation, params object[] args)
{ }
10![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
protected virtual void PostProceed(IInvocation invocation, ref object returnValue, params object[] args)
{ }
11![](/Images/OutliningIndicators/InBlock.gif)
12
public virtual object Intercept(IInvocation invocation, params object[] args)
13![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
14
PreProceed(invocation, args);
15
object retValue = invocation.Proceed(args);
16
PostProceed(invocation, ref retValue, args);
17
return retValue;
18
}
19
}
20
}
如果只是简单的拦截处理,重载其
void PostProceed(IInvocation invocation, ref object returnValue, params object[] args)
void PreProceed(IInvocation invocation, params object[] args)
两个方法就可以了,但是我们这里需要直接重载Intercept方法。
在Intercept方法判断了调用方法button对象,通过其名字判断了是否具有执行方法的权限,有则执行,没有就忽略。
做好了拦截器,可以来产生窗体的代理了
1![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//******************************
2
* 作者:米小波
3
* 日期:2005-12-05
4
* ****************************/
5
using System;
6
using System.Collections;
7
using System.Windows.Forms;
8
using System.Configuration;
9![](/Images/OutliningIndicators/None.gif)
10
using Castle.DynamicProxy;
11![](/Images/OutliningIndicators/None.gif)
12
namespace PopedomDemo
13![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
14
static class Program
15![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
16![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
17
/// 全局权限信息
18
/// </summary>
19
public static Hashtable PopedomList = new Hashtable();
20![](/Images/OutliningIndicators/InBlock.gif)
21![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
22
/// The main entry point for the application.
23
/// </summary>
24
[STAThread]
25
static void Main()
26![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
27
28
PopedomList.Clear();
29
30
//从配置文件读取权限信息
31
IDictionary dir = (IDictionary)System.Configuration.ConfigurationSettings.GetConfig("PopedomControlList");
32
string[] keys = new string[dir.Keys.Count];
33
string[] values = new string[dir.Keys.Count];
34
dir.Keys.CopyTo(keys, 0);
35
dir.Values.CopyTo(values, 0);
36
for (int i = 0; i < keys.Length; i++)
37![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
38
PopedomList.Add(keys[i], values[i]);
39
}
40
try
41![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
42
ProxyGenerator gen = new ProxyGenerator();
43
frmDemoMain frm = (frmDemoMain)gen.CreateClassProxy(typeof(frmDemoMain), new MyInterceptor());
44![](/Images/OutliningIndicators/InBlock.gif)
45
//Application.EnableVisualStyles();
46
//Application.SetCompatibleTextRenderingDefault(false);
47
Application.Run(frm);
48
}
49
catch (Exception ex)
50![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
51
string msg = ex.Message;
52
}
53![](/Images/OutliningIndicators/InBlock.gif)
54![](/Images/OutliningIndicators/InBlock.gif)
55
}
56
}
57
}
代码中前半部分是读取权限信息,后面则会为该窗体生成一个动态的代理
ProxyGenerator gen = new ProxyGenerator();
frmDemoMain frm = (frmDemoMain)gen.CreateClassProxy(typeof(frmDemoMain), new MyInterceptor());
记住有一点,需要被拦截处理的方法需要是虚方法,可被重载的,其实动态代理的生成原理就是继承了该类,并重载了其虚方法。
所以3个按钮的事件方法可能是这样的:
1
private void frmDemoMain_Load(object sender, EventArgs e)
2![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
}
4![](/Images/OutliningIndicators/None.gif)
5
public virtual void btnOne_Click(object sender, EventArgs e)
6![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
7
MessageBox.Show("BtnOne Process-1");
8
}
9![](/Images/OutliningIndicators/None.gif)
10
public virtual void btnTwo_Click(object sender, EventArgs e)
11![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
12
MessageBox.Show("BtnTwo Process-2");
13
}
14![](/Images/OutliningIndicators/None.gif)
15
public virtual void btnThree_Click(object sender, EventArgs e)
16![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
17
MessageBox.Show("BtnTwo Process-3");
18
}
19![](/Images/OutliningIndicators/None.gif)
写完了,回头看看代码,对于窗体里面的逻辑几乎不会增加任何与权限有关的代码,很干净。而且动态代理使用的委托技术,并不会对性能造成影响,所以利用它来处理与业务无关的方面是再好不过啦
本示例完整的程序代码可以到https://files.cnblogs.com/mixiaobo/PopedomDemo.rar下载