基于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。
并且针对方法中的传引用的参数,进行了处理,使其能够对传引用的参数进行赋值。
下图为整个解决方案的结构:

测试的接口:
public interface IMyTest
{
int Test1();
void Test2();
int Test3(int value);
TestModel Test4(ref TestModel T);
void Test5(TestModel T);
void Test6(out int value);
void Test7(ref int value);
int Test8(int value = );
int Test9(int value1 = , int value2 = );
int Test10(params int[] values);
int Test11(ref List<int> lst);
int Test12(TestEnumModel m);
TestEnumModel Test13(TestEnumModel m);
T Test14<T>(T m);
string Test14<T>(T m, int value);
string Test14<T>(T m, string value);
string Test14<T>(T m, TestModel model);
}
IMyTest接口
public interface IMyTest2<T>
{
T Test(T aa);
}
IMyTest2泛型接口
DTO对象:
public class TestModel
{
public int A { get; set; }
} public class TestImpModel : TestModel
{
public string B { get; set; }
} public enum TestEnumModel
{
A = ,
B =
}
DTO对象们
具体实现:
internal class MyTest : IMyTest
{
public int Test1()
{
return ;
} public void Test2()
{ } public int Test3(int value)
{
return value + ;
} public TestModel Test4(ref TestModel T)
{
T.A = T.A + ;
return T;
} public void Test5(TestModel T)
{
T.A = T.A + ;
} public void Test6(out int value)
{
value = ;
} public void Test7(ref int value)
{
value++;
} public int Test8(int value = )
{
return value;
} public int Test9(int value1 = , int value2 = )
{
return value1 + value2;
} public int Test10(params int[] values)
{
return values.Sum();
} public int Test11(ref List<int> lst)
{
lst.Add();
return lst.Sum();
} public int Test12(TestEnumModel m)
{
return (int)m;
} public TestEnumModel Test13(TestEnumModel m)
{
return m;
} public T Test14<T>(T m)
{
return m;
} public string Test14<T>(T m, int value)
{
return m.ToString() + value.ToString();
} public string Test14<T>(T m, string value)
{
return m.ToString() + value;
} public string Test14<T>(T m, TestModel model)
{
model.A += ;
return m.ToString() + model.A.ToString();
}
}
实现了IMyTest的MyTest类
internal class MyTest2<T> : IMyTest2<T>
{
public T Test(T aa)
{
return aa;
}
}
实现了IMyTest2的MyTest2泛型类
测试用例:
[TestMethod]
public void TestMethod1()
{
Assert.AreEqual(, MyCreator.Create<IMyTest>().Test1());
} [TestMethod]
public void TestMethod2()
{
MyCreator.Create<IMyTest>().Test2();
} [TestMethod]
public void TestMethod3()
{
Assert.AreEqual(, MyCreator.Create<IMyTest>().Test3());
Assert.AreEqual(, MyCreator.Create<IMyTest>().Test3());
} [TestMethod]
public void TestMethod4()
{
var tm = new TestModel() { A = };
var t = MyCreator.Create<IMyTest>().Test4(ref tm);
Assert.AreEqual(, t.A);
Assert.AreEqual(, tm.A);
} [TestMethod]
public void TestMethod5()
{
var t = new TestModel() { A = };
MyCreator.Create<IMyTest>().Test5(t);
Assert.AreEqual(, t.A);
} [TestMethod]
public void TestMethod6()
{
int i = ;
MyCreator.Create<IMyTest>().Test6(out i);
Assert.AreEqual(, i);
} [TestMethod]
public void TestMethod7()
{
int i = ;
MyCreator.Create<IMyTest>().Test7(ref i);
Assert.AreEqual(, i);
} [TestMethod]
public void TestMethod8()
{
Assert.AreEqual(, MyCreator.Create<IMyTest>().Test8());
} [TestMethod]
public void TestMethod9()
{
Assert.AreEqual(, MyCreator.Create<IMyTest>().Test9(value2: ));
} [TestMethod]
public void TestMethod10()
{
Assert.AreEqual(, MyCreator.Create<IMyTest>().Test10(, ));
} [TestMethod]
public void TestMethod11()
{
List<int> lst = new List<int>();
Assert.AreEqual(, MyCreator.Create<IMyTest>().Test11(ref lst));
Assert.AreEqual(, lst.Count);
Assert.AreEqual(, lst[]);
} [TestMethod]
public void TestMethod12()
{
Assert.AreEqual(, MyCreator.Create<IMyTest>().Test12(TestEnumModel.B));
} [TestMethod]
public void TestMethod13()
{
Assert.AreEqual(TestEnumModel.B, MyCreator.Create<IMyTest>().Test13(TestEnumModel.B));
} [TestMethod]
public void TestMethod14()
{
Assert.AreEqual(TestEnumModel.B, MyCreator.Create<IMyTest>().Test14(TestEnumModel.B));
} [TestMethod]
public void TestMethod15()
{
Assert.AreEqual("B123", MyCreator.Create<IMyTest>().Test14(TestEnumModel.B, ));
} [TestMethod]
public void TestMethod16()
{
Assert.AreEqual("Baaaaa", MyCreator.Create<IMyTest>().Test14(TestEnumModel.B, "aaaaa"));
} [TestMethod]
public void TestMethod17()
{
TestImpModel m = new TestImpModel() { A = , B = "" };
Assert.AreEqual("B2", MyCreator.Create<IMyTest>().Test14(TestEnumModel.B, m));
Assert.AreEqual(, m.A);
Assert.AreEqual("", m.B);
} [TestMethod]
public void TestMethod18()
{
TestImpModel m = new TestImpModel() { A = , B = "" };
var n = MyCreator.Create<IMyTest2<TestImpModel>>().Test(m);
Assert.AreEqual(, n.A);
Assert.AreEqual("", n.B);
}
18个简单的测试用例
项目源代码:DynamicWCF.rar
基于Autofac, Castle.DynamicProxy的动态WCF解决方案(原创)的更多相关文章
- ASP.NET Core搭建多层网站架构【9.2-使用Castle.Core实现动态代理拦截器】
2020/01/31, ASP.NET Core 3.1, VS2019, Autofac.Extras.DynamicProxy 4.5.0, Castle.Core.AsyncIntercepto ...
- Castle.DynamicProxy Part 1: ClassProxy
1.Castle中代理对象的分类 总的来说,代理对象大概可以分为2大类: 1.继承类型的代理对象 一类是继承类型的代理类.即:有一个类A,它的代理类是B.B是继承自A的.调用代理类B中的方法时,可以通 ...
- .NET 通过 Autofac 和 DynamicProxy 实现AOP
什么是AOP?引用百度百科:AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.实现AOP主要由两 ...
- Autofac高级用法之动态代理
前言 Autofac的DynamicProxy来自老牌的Castle项目.DynamicProxy(以下称为动态代理)起作用主要是为我们的类生成一个代理类,这个代理类可以在我们调用原本类的方法之前,调 ...
- 【转】Autofac高级用法之动态代理
原文:http://www.cnblogs.com/stulzq/p/8547839.html 前言 Autofac的DynamicProxy来自老牌的Castle项目.DynamicProxy(以下 ...
- Castle DynamicProxy基本用法(AOP)
本文介绍AOP编程的基本概念.Castle DynamicProxy(DP)的基本用法,使用第三方扩展实现对异步(async)的支持,结合Autofac演示如何实现AOP编程. AOP 百科中关于AO ...
- 使用Castle DynamicProxy (AOP)
在本文中,我将引导您了解.NET环境中的面向方面编程(AOP)概念,以及如何使用Castle DynamicProxy创建和附加方面.在我们开始之前,让我快速介绍AOP和 IoC.如果您已经熟悉这些 ...
- WCF分布式开发步步为赢(2)自定义托管宿主WCF解决方案开发配置过程详解
上一节<WCF分布式框架基础概念>我们介绍了WCF服务的概念和通信框架模型,并给出了基于自定义托管服务的WCF程序的实现代码.考虑到WCF分布式开发项目中关于托管宿主服务配置和客户端添加引 ...
- [AOP系列]Autofac+Castle实现AOP事务
一.前言 最近公司新项目,需要搭架构进行开发,其中需要保证事务的一致性,经过一番查找,发现很多博文都是通过Spring.Net.Unity.PostSharp.Castle Windsor这些方式实现 ...
随机推荐
- git常见错误
一.如果输: $ git remote add origin git@github.com:djqiang(github帐号名)/gitdemo(项目名).git 提示出错信息:fat ...
- VB 中Sub和Function的区别
Sub可以理解为执行一个过车,一个操作. Function在执行完过后,还要返回一个结果. Sub:过程:Function:函数,可以带返回值. 语法: Sub SubName(参数1,参数2,... ...
- 外边距(padding)重叠的及解决办法
两个或多个块级盒子的垂直相邻边界会重合.结果的边界宽度是相邻边界宽度中最大的值.如果出现负边界,则在最大的正边界中减去绝对值最大的负边界.如果没有正边界,则从零中减去绝对值最大的负边界.注意:相邻的盒 ...
- css 居中
今天来总结一下自己知道的居中方法: 一.水平居中 1.text-align:center; 文字水平居中,也可以放在父元素中,强行让子元素居中. 2.margin: 0 auto; 使子元素在父 ...
- 关于as3调用js报“null为空或不是对象”错误
主要原因是:flash插件的object对象无ID属性. 顺便说下as3调用js的方法. as3引用: import flash.external.ExternalInterface; as3中调用 ...
- ODOO的命令行调用以及config默认值
通过odoo-bin 可以启动odoo server ,启动的过程中需要提供一些args,包括数据库设置,ip设置等 如果不想每次输入这些参数,可以直接修改odoo/tools/config.py中的 ...
- 解决Eclipse中文乱码 - 技术博客 - 51CTO技术博客 http://hsj69106.blog.51cto.com/1017401/595598/
解决Eclipse中文乱码 - 技术博客 - 51CTO技术博客 http://hsj69106.blog.51cto.com/1017401/595598/
- HDU 5964 平行四边形
假设直线L和L'相交于原点O.假设S ={s1,s2,...,sn}是平面上的n个点.你打 算找四个点满足如下条件:1. A ∈ L 而 A' ∈ L'.2. B,B'都属于S;即 B∈S 且 ...
- Monkey环境搭建
一.Monkey 1)Monkey是什么? Monkey是SDK中附带的一个工具.是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏 ...
- JS 控制CSS样式表
JS控制CSS所使用的方法: <style> .rule{ display: none; } </style> 你想要改变把他的display属性由none改为inline. ...