• 基于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

  • 相关阅读:
    问题:Failed to execute goal org.apache.maven.plugins:mavencompilerplugin:3.5.1:compile (defaultcompile)
    STL容器的内存分配
    C++中的引用到底是什么
    解决eclipse无法解析shared_ptr
    Deleted pointer causes undefined behaviour
    诞生于饭桌上的jcSQL语言
    状压dp做题笔记
    TC做题笔记
    数据结构做题笔记
    POI做题笔记
  • 原文地址:https://www.cnblogs.com/nickppa/p/4562347.html
Copyright © 2020-2023  润新知