设计模式学习——动态代理实现C#动态调用WebService(附源码)

简介:

对于这个问题,很很早以前就遇到了,当时并不理解。前段时间看了一下动态代理,对这个问题有了一些了解。

对于一般的webservice,可以通过添加web引用实现调用。但这样的缺点就是不够灵活,当webservice地址发生变化时需要重新添加引用,重新编译。这种缺点还稍微可以接受的。我遇到的应用场景是,程序运行之前无法知道webservice的地址,因为地址都存放于数据库中,使用时需要动态的调用。这样通过添加引用基本不可能实现,所以采用上述方法实现。

在采用这种方法时,首先遇到的问题就是:如何构造的代理类?

类似于javaJDK提供的有编译源文件的接口,.net也提供的有相关的类似的我们能够动态的生成源码并进行编译,从而动态的生成代理类。(当然不排除大牛通过解析语法规则直接生成二进制文件,而无需调用编译接口的。)

我们可以采用类似于下面的方法来动态的生成要编译的源码。

private CodeCompileUnit GetServiceCompileUnit(string webServiceUrl)

    {

        WebClient client = new WebClient();

        Stream stream = client.OpenRead(webServiceUrl);

//从这个url指向的的是一个xml文件,里面包含了该service的全部信息。

//进而通过解析xml文件从而可以生成要编译的源码。有兴趣的可以看一下xml的内容

ServiceDescription description = ServiceDescription.Read(stream);        ServiceDescriptionImporter importer = new ServiceDescriptionImporter();        importer.ProtocolName = "Soap";//使用的协议

        importer.Style = ServiceDescriptionImportStyle.Client;

importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;

importer.AddServiceDescription(description, """");  

     CodeNamespace nmspace = new CodeNamespace();

        nmspace.Name = "WebService";//生成类的名空间,可以根据需求指定

        CodeCompileUnit unit = new CodeCompileUnit();

        unit.Namespaces.Add(nmspace);

        ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);

        return unit;

    }

Unit返回的就是要进行编译的东西了。

 

下一步及时进行编译了。根据需求设置相关的编译参数后,就就可以进行编译了。就像下边这样。

 

 

 private CompilerResults Compile(CodeCompileUnit unit)

    {

        CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("CSharp");

        CompilerParameters compilerParameters = new CompilerParameters();

        compilerParameters.GenerateExecutable = false;

        compilerParameters.GenerateInMemory = true;

   //  cp.OutputAssembly = "D:\\Test.dll";这里也可以将变异的结果输出到dll文件中,从而可以查看编译的的结果。有兴趣的自己看一下。

     compilerParameters.ReferencedAssemblies.Add("System.dll");

        compilerParameters.ReferencedAssemblies.Add("System.XML.dll");

        compilerParameters.ReferencedAssemblies.Add("System.Web.Services.dll");

        compilerParameters.ReferencedAssemblies.Add("System.Data.dll");

  CompilerResults compilerResults = codeDomProvider.CompileAssemblyFromDom(compilerParameters, unit);

        if (compilerResults.Errors.HasErrors)

        {

            string errors = "";

            foreach (var item in compilerResults.Errors)

            {

                errors += item.ToString() + Environment.NewLine;

            }

            throw new Exception("Compile error:" + errors);

        }

        return compilerResults;

    }

 

有了编译的结果,已经生成了代理类,下一步要做的就是将这个代理类加载到内存当中。

   Assembly asm = result.CompiledAssembly;

        object obj = asm.CreateInstance("WebService." + proxy._className);

这样就将代理类加载到了内存当中,并且长生了一个实例,将这个实例返回就可以根据他来调用所需的方法了。当然调用方法时可能还是要用到反射,因为已知的可能仅仅只有方法名和它所需的参数。




本文转自HDDevTeam 51CTO博客,原文链接:http://blog.51cto.com/hddev/628288,如需转载请自行联系原作者

相关文章
设计模式 存储 人工智能
196 0
|
5月前
|
设计模式 存储 缓存
Netty源码—9.性能优化和设计模式
本文主要介绍了Netty的两大性能优化工具、FastThreadLocal的源码和总结、Recycler的设计理念/使用/四个核心组件/初始化/对象获取/对象回收/异线程收割对象和总结,以及Netty设计模式的单例模式和策略模式。
206 53
|
8月前
|
存储 SQL 开发框架
c# erp源码(简单进销存)
c# erp源码(简单进销存)
431 1
|
9月前
|
设计模式 存储 Java
「全网最细 + 实战源码案例」设计模式——责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,允许将请求沿着处理者链进行发送。每个处理者可以处理请求或将其传递给下一个处理者,从而实现解耦和灵活性。其结构包括抽象处理者(Handler)、具体处理者(ConcreteHandler)和客户端(Client)。适用于不同方式处理不同种类请求、按顺序执行多个处理者、以及运行时改变处理者及其顺序的场景。典型应用包括日志处理、Java Web过滤器、权限认证等。
208 13
「全网最细 + 实战源码案例」设计模式——责任链模式
|
9月前
|
设计模式 存储 算法
「全网最细 + 实战源码案例」设计模式——命令模式
命令模式(Command Pattern)是一种行为型设计模式,将请求封装成独立对象,从而解耦请求方与接收方。其核心结构包括:Command(命令接口)、ConcreteCommand(具体命令)、Receiver(接收者)和Invoker(调用者)。通过这种方式,命令的执行、撤销、排队等操作更易扩展和灵活。 适用场景: 1. 参数化对象以操作。 2. 操作放入队列或远程执行。 3. 实现回滚功能。 4. 解耦调用者与接收者。 优点: - 遵循单一职责和开闭原则。 - 支持命令组合和延迟执行。 - 可实现撤销、恢复功能。 缺点: - 增加复杂性和类数量。
309 14
「全网最细 + 实战源码案例」设计模式——命令模式
|
9月前
|
设计模式 算法 开发者
「全网最细 + 实战源码案例」设计模式——策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,用于定义一系列可替换的算法或行为,并将它们封装成独立的类。通过上下文持有策略对象,在运行时动态切换算法,提高代码的可维护性和扩展性。适用于需要动态切换算法、避免条件语句、经常扩展算法或保持算法独立性的场景。优点包括符合开闭原则、运行时切换算法、解耦上下文与策略实现、减少条件判断;缺点是增加类数量和策略切换成本。示例中通过定义抽象策略接口和具体策略类,结合上下文类实现动态算法选择。
310 8
「全网最细 + 实战源码案例」设计模式——策略模式
|
9月前
|
设计模式 SQL 算法
「全网最细 + 实战源码案例」设计模式——模板方法模式
模板方法模式是一种行为型设计模式,定义了算法的骨架并在父类中实现不变部分,将可变部分延迟到子类实现。通过这种方式,它避免了代码重复,提高了复用性和扩展性。具体步骤由抽象类定义,子类实现特定逻辑。适用于框架设计、工作流和相似算法结构的场景。优点包括代码复用和符合开闭原则,缺点是可能违反里氏替换原则且灵活性较低。
235 7
「全网最细 + 实战源码案例」设计模式——模板方法模式
|
9月前
|
设计模式 存储 安全
「全网最细 + 实战源码案例」设计模式——组合模式
组合模式(Composite Pattern)是一种结构型设计模式,用于将对象组合成树形结构以表示“部分-整体”的层次结构。它允许客户端以一致的方式对待单个对象和对象集合,简化了复杂结构的处理。组合模式包含三个主要组件:抽象组件(Component)、叶子节点(Leaf)和组合节点(Composite)。通过这种模式,客户端可以统一处理简单元素和复杂元素,而无需关心其内部结构。适用于需要实现树状对象结构或希望以相同方式处理简单和复杂元素的场景。优点包括支持树形结构、透明性和遵循开闭原则;缺点是可能引入不必要的复杂性和过度抽象。
287 22
|
9月前
|
设计模式 存储 缓存
「全网最细 + 实战源码案例」设计模式——享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在减少大量相似对象的内存消耗。通过分离对象的内部状态(可共享、不变)和外部状态(依赖环境、变化),它有效减少了内存使用。适用于存在大量相似对象且需节省内存的场景。模式优点包括节省内存和提高性能,但会增加系统复杂性。实现时需将对象成员变量拆分为内在和外在状态,并通过工厂类管理享元对象。
355 92
|
10月前
|
设计模式 前端开发 数据库
「全网最细 + 实战源码案例」设计模式——桥接模式
桥接模式(Bridge Pattern)是一种结构型设计模式,通过将抽象部分与实现部分分离,使它们可以独立变化,从而降低代码耦合度,避免类爆炸,提高可扩展性。其结构包括实现类接口、具体实现类、抽象类和精确抽象类。适用于多维度扩展类、隐藏实现细节、简化庞杂类以及运行时切换实现方法的场景。优点包括高扩展性、隐藏实现细节、遵循开闭原则和单一职责原则;缺点是可能增加代码复杂度。示例中展示了不同操作系统播放不同格式视频文件的实现。
236 19

热门文章

最新文章