C#实现动态灵活调用业务方法的机制

简介:
+关注继续查看

问题的提出:
在某些应用中往往会遇到这样的情况,例如最近遇到一个应用大致需要做这样的事情:
1.有几个比较类似的业务,但是每个的处理方法和输出不同;
2.需要动态的处理这些业务,例如某个时间可能需要处理甲业务,某个时间需要处理乙业务;
3.需要处理的业务数量不确定,随时可能有增减情况;
4.希望主体程序比较固定;



问题的分析:
我的想法是将这些业务规范为一些类库,固定好规范的接口。然后将这些Dll统一放在某个目录下面,目录中的Dll可以采取简单的XCopy方式来增删,并且需要保证主体程序不会长时间占用某个Dll资源,调用完就释放。


解决方法实验:
先将主要技术关键点抽取出来,关键就是建立一个可以动态调用某个目录下面的Dll中的某个方法的机制,因此先做一些简单的测试,将这个机制的建立弄清晰。

下面是这个简单的机制:
先建立了三个简单的类库,ADll,BDll,CDll。主体调用程序是testReadDll,它需要调用相对目录Dlls下面的全部Dll中的makeStr,没有输出错误信息继续执行下一个Dll。其中ADll和BDll都有类似的接口(这里并没有将接口抽象出来),但CDll为了测试,并没有实现类似的接口。

假设ADll和BDll实现了方法makeStr,CDll没有实现这个方法。

由于.NET的强大的反射机制,实现这些功能并不困难。

主体程序中调用Dll指定方法的代码:

None.gif        private void btnInvoke_Click(object sender, System.EventArgs e)
ExpandedBlockStart.gif        {
InBlock.gif            lstValue.Items.Clear();
InBlock.gif            DirectoryInfo d = new DirectoryInfo("Dlls");  // 目录和当前EXE在同一个目录下
InBlock.gif
            foreach (FileInfo file in d.GetFiles("*.dll"))
ExpandedSubBlockStart.gif            {
InBlock.gif                string pathName = d.FullName + "\" + file.Name;
InBlock.gif                // 根据文件名获取程序集信息
InBlock.gif
                Assembly assembly = Assembly.LoadFrom(pathName);                
InBlock.gif                lstValue.Items.Insert(0,assembly.FullName + "的调用结果:");
InBlock.gif                try 
ExpandedSubBlockStart.gif                {
InBlock.gif                    foreach (Type t in assembly.GetTypes())
ExpandedSubBlockStart.gif                    {
InBlock.gif                        Object obj = t.InvokeMember(null,
InBlock.gif                            BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance,
InBlock.gif                            null,null,null);
InBlock.gif                        string s = (string)t.InvokeMember("makeStr",
InBlock.gif                            BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance,
InBlock.gif                            null,obj,null);
InBlock.gif                        lstValue.Items.Insert(0,s);
InBlock.gif
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }
 
InBlock.gif                catch (Exception ex)
ExpandedSubBlockStart.gif                {
InBlock.gif                    lstValue.Items.Insert(0,ex.ToString());
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif        
ExpandedBlockEnd.gif        }

None.gif

ADll相关代码:
None.gifusing System;
None.gif
None.gifnamespace ADll
ExpandedBlockStart.gif{
ExpandedSubBlockStart.gif    /// <summary>
InBlock.gif    
/// Class1 的摘要说明。
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class AClass
ExpandedSubBlockStart.gif    {
InBlock.gif        public AClass()
ExpandedSubBlockStart.gif        {
InBlock.gif            //
InBlock.gif            
// TODO: 在此处添加构造函数逻辑
InBlock.gif            
//
ExpandedSubBlockEnd.gif
        }

InBlock.gif
InBlock.gif        public string makeStr()
ExpandedSubBlockStart.gif        {
InBlock.gif            string retStr;
InBlock.gif            retStr = "ADll make Stringdot.gif";
InBlock.gif            return retStr;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
BDll相关代码:
None.gifusing System;
None.gif
None.gifnamespace BDll
ExpandedBlockStart.gif{
ExpandedSubBlockStart.gif    /// <summary>
InBlock.gif    
/// Class1 的摘要说明。
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class BClass
ExpandedSubBlockStart.gif    {
InBlock.gif        public BClass()
ExpandedSubBlockStart.gif        {
InBlock.gif            //
InBlock.gif            
// TODO: 在此处添加构造函数逻辑
InBlock.gif            
//
ExpandedSubBlockEnd.gif
        }

InBlock.gif
InBlock.gif        public string makeStr()
ExpandedSubBlockStart.gif        {
InBlock.gif            string retStr;
InBlock.gif            retStr = "BDll make Stringdot.gifModifydot.gifAdd..ok2";
InBlock.gif            return retStr;
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
CDll相关代码:
None.gifusing System;
None.gif
None.gifnamespace CDll
ExpandedBlockStart.gif{
ExpandedSubBlockStart.gif    /// <summary>
InBlock.gif    
/// Class1 的摘要说明。
ExpandedSubBlockEnd.gif    
/// </summary>

InBlock.gif    public class CClass
ExpandedSubBlockStart.gif    {
InBlock.gif        public CClass()
ExpandedSubBlockStart.gif        {
InBlock.gif            //
InBlock.gif            
// TODO: 在此处添加构造函数逻辑
InBlock.gif            
//
ExpandedSubBlockEnd.gif
        }

InBlock.gif
InBlock.gif        public string makeStr2()
ExpandedSubBlockStart.gif        {
InBlock.gif            string retStr;
InBlock.gif            retStr = "cDll make Stringdot.gifModifydot.gif";
InBlock.gif            return retStr;
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
机制测试:
1.先将ADll,BDll编译通过放到Dlls下面,运行testReadDll调用makeStr结果如下:
testDlls1.JPG
2.不需要退出testReadDll,将ADll删除,运行testReadDll调用makeStr结果如下:
testDlls2.JPG
3.不需要退出testReadDll,将ADll和CDll再次放入Dlls,运行testReadDll调用makeStr结果如下:
testDlls3.JPG
4.那么如果ADll和BDll增加一个副本又如何呢?
  不需要退出testReadDll,为ADll和BDll增加一个副本在Dlls如下图:
testDlls4.JPG
运行testReadDll调用makeStr结果如下:
testDlls5.JPG


小结:
由此可以看出,这样的机制是十分灵活的,只要将业务相关的Dll放入这个目录下面就可以了。
另外,对于副本的调用结果是一样的,当然这些可以在程序中再做一些限制,避免重复调用。

调用的顺序和时间规则也可以在程序中做定义或者用一个配置文件来限制。


本文转自风前絮~~博客园博客,原文链接:http://www.cnblogs.com/windsails/archive/2004/09/07/40574.html,如需转载请自行联系原作者

相关文章
|
2月前
|
消息中间件 存储 负载均衡
|
2月前
|
消息中间件 存储 Kafka
|
8月前
|
BI
对象的自治和行为的扩展与适配
对象的自治和行为的扩展与适配
对象的自治和行为的扩展与适配
|
12月前
|
缓存
读源码长知识 | 动态扩展类并绑定生命周期的新方式
在阅读viewModelScope源码时,发现了一种新的方式。 协程需隶属于某 CoroutineScope ,以实现structured-concurrency,而 CoroutineScope 应
97 0
|
存储 SQL 数据可视化
模板化的封装,降低业务代码开发
做这些业务设计时,核心思想是:把常用的逻辑进行封装,流程设计为可配置,这样即可在一定时间内应对业务的需求和变化,降低开发成本的支出,从而使研发更侧重核心业务的管理和抽象封装等内容。
90 0
模板化的封装,降低业务代码开发
|
存储 缓存 JavaScript
ServiceWorker工作原理、生命周期和使用场景
service worker 是现代web开发的关键部分,在最近几年获得了关注,这都要归功于 PWA(渐进式 Web 应用程序) 的流行。service worker 通过向典型的 Web 应用程序添加后台同步、离线渲染和推送通知等功能,缩小了本机应用程序和 Web 应用程序之间的差距,主要任务之一是充当代理。
417 0
ServiceWorker工作原理、生命周期和使用场景
|
Java 调度 开发工具
QuickTask动态脚本支持框架整体介绍篇
一个简单的动态脚本调度框架,支持运行时,实时增加,删除和修改动态脚本,可用于后端的进行接口验证、数据订正,执行定时任务或校验脚本
176 0
QuickTask动态脚本支持框架整体介绍篇
|
分布式计算 资源调度 大数据
静态模式和统一模式_2|学习笔记
快速学习 静态模式和统一模式_2
静态模式和统一模式_2|学习笔记
|
运维
实例维护属性-让您的实例更可控
阿里云给实例加入了维护属性这个属性,通过对该属性的修改,您可以自主选择实例出现非预期宕机或者主动运维事件之后的状态,为您的操作提供更高的透明度和便捷度
2308 0
实例维护属性-让您的实例更可控
|
缓存 关系型数据库 数据库
相关产品
云迁移中心
推荐文章
更多