基于Autofac, Castle.DynamicProxy的动态WCF解决方案(原创)

本方案解决了下面3个主要的问题:

1、减少配置,为了避免每次新增service都需要去修改配置文件,包括服务器端跟各个客户端的。

2、能够使用函数重载,泛型函数,以及泛型类。

3、使项目能够快速地在wcf与直接调用dll之间切换。

整个解决方案分为四块内容:1、客户端,2、契约层,3、服务端,4、实现层

1、客户端:只能看到契约层,而看不到具体的实现;但也可以通过直接引用实现层,从而脱离wcf(需要修改工厂方法,也可以改进一下,通过配置文件来做这个事情,但这个不是本解决方案的重点,有兴趣的可以自己去实现)。

2、契约层:包含DTO对象模型跟各个服务接口

3、服务端:能看到契约层跟实现层

4、实现层:使用Autofac跟Castle.DynamicProxy进行IOC跟AOP(动态代理中的拦截器)

为解决第一个问题,早些年,已有人通过只暴露WCF的一个服务,而向该服务传递类名,函数名,参数数组来解决这一问题,但是用字符串在我看来实在是不太好,谁能保证自己在编码的时候不会把字符串给写错呢,而且万一需要更改服务名,vs的代码重构机制也处理不了字符串。所以我觉得利用接口,应该是最好的解决方案,但问题是谁又能在不知道具体的实现类的情况下,而针对接口凭空实例化出来一个对象呢。答案是有的,用Emit指令,不过Emit指令实在是有点难。此时我又想到了单元测试中常用的Rhino Mocks跟moq框架,便去查看了它们的源代码,我发现其中一个用的.net自带的真实代理(RealProxy),另外个用的是Castle.DynamicProxy,个人比较喜欢Castle.DynamicProxy,就用了它的CreateInterfaceProxyWithoutTarget,然后在自定义的拦截器中去调用实际的WCF服务,将返回回来的值设置给invocation.ReturnValue。

并且针对方法中的传引用的参数,进行了处理,使其能够对传引用的参数进行赋值。

下图为整个解决方案的结构:

测试的接口:

 1 public interface IMyTest
 2     {
 3         int Test1();
 4         void Test2();
 5         int Test3(int value);
 6         TestModel Test4(ref TestModel T);
 7         void Test5(TestModel T);
 8         void Test6(out int value);
 9         void Test7(ref int value);
10         int Test8(int value = 8);
11         int Test9(int value1 = 0, int value2 = 0);
12         int Test10(params int[] values);
13         int Test11(ref List<int> lst);
14         int Test12(TestEnumModel m);
15         TestEnumModel Test13(TestEnumModel m);
16         T Test14<T>(T m);
17         string Test14<T>(T m, int value);
18         string Test14<T>(T m, string value);
19         string Test14<T>(T m, TestModel model);
20     }

IMyTest接口

1 public interface IMyTest2<T>
2     {
3         T Test(T aa);
4     }

IMyTest2泛型接口

DTO对象:

 1 public class TestModel
 2     {
 3         public int A { get; set; }
 4     }
 5
 6 public class TestImpModel : TestModel
 7     {
 8         public string B { get; set; }
 9     }
10
11 public enum TestEnumModel
12     {
13         A = 0,
14         B = 1
15     }

DTO对象们

具体实现:

 1 internal class MyTest : IMyTest
 2     {
 3         public int Test1()
 4         {
 5             return 1;
 6         }
 7
 8         public void Test2()
 9         {
10
11         }
12
13         public int Test3(int value)
14         {
15             return value + 1;
16         }
17
18         public TestModel Test4(ref TestModel T)
19         {
20             T.A = T.A + 1;
21             return T;
22         }
23
24         public void Test5(TestModel T)
25         {
26             T.A = T.A + 1;
27         }
28
29         public void Test6(out int value)
30         {
31             value = 3;
32         }
33
34         public void Test7(ref int value)
35         {
36             value++;
37         }
38
39
40         public int Test8(int value = 8)
41         {
42             return value;
43         }
44
45
46         public int Test9(int value1 = 0, int value2 = 0)
47         {
48             return value1 + value2;
49         }
50
51
52         public int Test10(params int[] values)
53         {
54             return values.Sum();
55         }
56
57
58         public int Test11(ref List<int> lst)
59         {
60             lst.Add(3);
61             return lst.Sum();
62         }
63
64         public int Test12(TestEnumModel m)
65         {
66             return (int)m;
67         }
68
69         public TestEnumModel Test13(TestEnumModel m)
70         {
71             return m;
72         }
73
74         public T Test14<T>(T m)
75         {
76             return m;
77         }
78
79         public string Test14<T>(T m, int value)
80         {
81             return m.ToString() + value.ToString();
82         }
83
84         public string Test14<T>(T m, string value)
85         {
86             return m.ToString() + value;
87         }
88
89         public string Test14<T>(T m, TestModel model)
90         {
91             model.A += 1;
92             return m.ToString() + model.A.ToString();
93         }
94     }

实现了IMyTest的MyTest类

1 internal class MyTest2<T> : IMyTest2<T>
2     {
3         public T Test(T aa)
4         {
5             return aa;
6         }
7     }

实现了IMyTest2的MyTest2泛型类

测试用例:

  1 [TestMethod]
  2         public void TestMethod1()
  3         {
  4             Assert.AreEqual(1, MyCreator.Create<IMyTest>().Test1());
  5         }
  6
  7         [TestMethod]
  8         public void TestMethod2()
  9         {
 10             MyCreator.Create<IMyTest>().Test2();
 11         }
 12
 13         [TestMethod]
 14         public void TestMethod3()
 15         {
 16             Assert.AreEqual(4, MyCreator.Create<IMyTest>().Test3(3));
 17             Assert.AreEqual(3, MyCreator.Create<IMyTest>().Test3(2));
 18         }
 19
 20         [TestMethod]
 21         public void TestMethod4()
 22         {
 23             var tm = new TestModel() { A = 2 };
 24             var t = MyCreator.Create<IMyTest>().Test4(ref tm);
 25             Assert.AreEqual(3, t.A);
 26             Assert.AreEqual(3, tm.A);
 27         }
 28
 29         [TestMethod]
 30         public void TestMethod5()
 31         {
 32             var t = new TestModel() { A = 2 };
 33             MyCreator.Create<IMyTest>().Test5(t);
 34             Assert.AreEqual(2, t.A);
 35         }
 36
 37         [TestMethod]
 38         public void TestMethod6()
 39         {
 40             int i = 0;
 41             MyCreator.Create<IMyTest>().Test6(out i);
 42             Assert.AreEqual(3, i);
 43         }
 44
 45         [TestMethod]
 46         public void TestMethod7()
 47         {
 48             int i = 0;
 49             MyCreator.Create<IMyTest>().Test7(ref i);
 50             Assert.AreEqual(1, i);
 51         }
 52
 53         [TestMethod]
 54         public void TestMethod8()
 55         {
 56             Assert.AreEqual(8, MyCreator.Create<IMyTest>().Test8());
 57         }
 58
 59         [TestMethod]
 60         public void TestMethod9()
 61         {
 62             Assert.AreEqual(12, MyCreator.Create<IMyTest>().Test9(value2: 12));
 63         }
 64
 65         [TestMethod]
 66         public void TestMethod10()
 67         {
 68             Assert.AreEqual(3, MyCreator.Create<IMyTest>().Test10(1, 2));
 69         }
 70
 71         [TestMethod]
 72         public void TestMethod11()
 73         {
 74             List<int> lst = new List<int>();
 75             Assert.AreEqual(3, MyCreator.Create<IMyTest>().Test11(ref lst));
 76             Assert.AreEqual(1, lst.Count);
 77             Assert.AreEqual(3, lst[0]);
 78         }
 79
 80         [TestMethod]
 81         public void TestMethod12()
 82         {
 83             Assert.AreEqual(1, MyCreator.Create<IMyTest>().Test12(TestEnumModel.B));
 84         }
 85
 86         [TestMethod]
 87         public void TestMethod13()
 88         {
 89             Assert.AreEqual(TestEnumModel.B, MyCreator.Create<IMyTest>().Test13(TestEnumModel.B));
 90         }
 91
 92         [TestMethod]
 93         public void TestMethod14()
 94         {
 95             Assert.AreEqual(TestEnumModel.B, MyCreator.Create<IMyTest>().Test14(TestEnumModel.B));
 96         }
 97
 98         [TestMethod]
 99         public void TestMethod15()
100         {
101             Assert.AreEqual("B123", MyCreator.Create<IMyTest>().Test14(TestEnumModel.B, 123));
102         }
103
104         [TestMethod]
105         public void TestMethod16()
106         {
107             Assert.AreEqual("Baaaaa", MyCreator.Create<IMyTest>().Test14(TestEnumModel.B, "aaaaa"));
108         }
109
110         [TestMethod]
111         public void TestMethod17()
112         {
113             TestImpModel m = new TestImpModel() { A = 1, B = "3" };
114             Assert.AreEqual("B2", MyCreator.Create<IMyTest>().Test14(TestEnumModel.B, m));
115             Assert.AreEqual(1, m.A);
116             Assert.AreEqual("3", m.B);
117         }
118
119         [TestMethod]
120         public void TestMethod18()
121         {
122             TestImpModel m = new TestImpModel() { A = 1, B = "3" };
123             var n = MyCreator.Create<IMyTest2<TestImpModel>>().Test(m);
124             Assert.AreEqual(1, n.A);
125             Assert.AreEqual("3", n.B);
126         }

18个简单的测试用例

项目源代码:DynamicWCF.rar

时间: 2024-10-22 09:32:06

基于Autofac, Castle.DynamicProxy的动态WCF解决方案(原创)的相关文章

.NET 通过 Autofac 和 DynamicProxy 实现AOP

什么是AOP?引用百度百科:AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.实现AOP主要由两种方式,一种是编译时静态植入,优点是效率高,缺点是缺乏灵活性,.net下postsharp为代表者(这个是收费的).另一种方式是动态代理,优缺点与前者相反,动态为目标类型创建代理,通过代理调用实现拦截.AOP能做什么,常见的用例是事务处理.日志记录等等.下面就讲讲Autofac怎么实现AOP,Aut

ASP.NET Core搭建多层网站架构【8.2-使用Castle.Core实现动态代理拦截器】

2020/01/30, ASP.NET Core 3.1, VS2019, 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[8.2-使用Castle.Core实现动态代理拦截器] 使用Autofac替换原生的依赖注入 文章目录 此分支项目代码 本章节介绍了使用Autofac代替原生的依赖注入,使用Autofac为的是后面配合Castle.Core做AOP动态代理 原文地址:https://www.cnblogs.com/kasnti/p/12244544.html

基于DDD领域驱动设计的WCF+EF+WPF分层框架

目录置顶: 关于项目--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(1) 架构搭建--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(2) WCF服务端具体实现---------基于DDD领域驱动设计的WCF+EF+WPF分层框架(3) WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4) Domain具体实现------------基于DDD领域驱动设计的WCF+EF

WCF分布式开发步步为赢(2)自定义托管宿主WCF解决方案开发配置过程详解

上一节<WCF分布式框架基础概念>我们介绍了WCF服务的概念和通信框架模型,并给出了基于自定义托管服务的WCF程序的实现代码.考虑到WCF分布式开发项目中关于托管宿主服务配置和客户端添加引用.两个环节最容易出错.对于大部分想学习WCF分布式开发的人来说,成功开发.配置.部署第一个自己的WCF服务困难重重.很多资料都介绍了WCF的基本概念.但是对于实际的项目开发过程介绍粗略,给入门者带来诸多不便.今天我们就来补充一节WCF分布式开发一个完整解决方案的开发和配置过程.本节基本结构是:首先介绍[1]

架构搭建----基于DDD领域驱动设计的WCF+EF+WPF分层框架(2)

写在最前面:转载请注明出处 目录置顶: 关于项目--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(1) 架构搭建--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(2) WCF服务端具体实现---------基于DDD领域驱动设计的WCF+EF+WPF分层框架(3) WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4) Domain具体实现------------基于DD

基于 Spring 和 iBATIS 的动态可更新多数据源持久层

前言 我们时常会遇到一些 web 项目,需要从不同的数据源中抓取数据来进行分析,而这些数据源是有可能变化的,需要用户来进行动态的维护和添加.可是,大多数的 web 程序使用了应用服务器或者容器中间件来管理数据源的生命周期,因此数据源的变化自然不能够独立于程序,而需要由专业人士去进行维护,必要时还需要重新发布程序来适应数据源的变化,而且数据源的个数.数据库的类型也都会有所限制. 那么怎样才可以突破以上这些局限,彻底实现由用户远程对数据源进行维护和管理的需求呢?本文提出了一个有效的解决方案,该方案的

【Spark】SparkStreaming-流处理-规则动态更新-解决方案

SparkStreaming-流处理-规则动态更新-解决方案 image2017-10-27_11-10-53.png (1067×738) elasticsearch-head Elasticsearch-sql client spark streaming reload_百度搜索 基于spark streaming的网管系统告警过滤算法的设计与实现 - 其它论文 - 道客巴巴 scala - Spark Streaming into HBase with filtering logic -

WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4)

写在最前面:转载请注明出处 目录置顶: 关于项目--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(1) 架构搭建--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(2) WCF服务端具体实现---------基于DDD领域驱动设计的WCF+EF+WPF分层框架(3) WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4) Domain具体实现------------基于DD

Castle.DynamicProxy 拦截器

前言:我们已经使用工厂模式得到需要的service对象,以下方法可以通过Castle.DynamicProxy给service对象的方法添加拦截器. /// <summary> /// 创建服务根据BLL接口 /// </summary> public static T CreateService<T>() where T : class { var service = serviceFactory.CreateService<T>(); //拦截,可以写日