WebServices 动态调用 接口自动创建 EMIT

通过使用 System.Reflection.Emit 动态创建代码,实现从WebService对象上抽离接口。从而方便实用。

  1. using System;  
  2. using System.Reflection;  
  3. using System.IO;  
  4. using System.Web;  
  5. using System.CodeDom;  
  6. using System.CodeDom.Compiler;  
  7. using System.Collections.Generic;  
  8. using System.Text;  
  9. using System.Net;  
  10. using System.Web.Services;  
  11. using System.Web.Services.Description;  
  12. using System.Web.Services.Protocols;  
  13. using System.Reflection.Emit;  
  14. using System.Net.Security;  
  15. using System.Security.Cryptography.X509Certificates;  
  16.   
  17.   
  18.   
  19. namespace GDC  
  20. {  
  21.     public static  class DynWebService  
  22.     {  
  23.         public static T GetWebServiceInterface<T>(string wsdlURL, string className) where T : class  
  24.         {  
  25.             object obj = GeObject(wsdlURL, className);  
  26.             return GetWrapper<T>(obj);  
  27.         }  
  28.   
  29.         static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)  
  30.         {  
  31.             return true;  
  32.         }  
  33.   
  34.         public static object GeObject(string wsdlURL, string className)  
  35.         {  
  36.             System.Net.ServicePointManager.ServerCertificateValidationCallback  
  37.                 = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);  
  38.   
  39.   
  40.             WebClient aWc = new WebClient();  
  41.             Stream aStream = aWc.OpenRead(wsdlURL);  
  42.             ServiceDescription aSD = ServiceDescription.Read(aStream);  
  43.             ServiceDescriptionImporter importer = new ServiceDescriptionImporter();  
  44.             importer.ProtocolName = "Soap";  
  45.             importer.Style = ServiceDescriptionImportStyle.Client;  
  46.             importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties  
  47.                 | System.Xml.Serialization.CodeGenerationOptions.GenerateNewAsync;  
  48.   
  49.             importer.AddServiceDescription(aSD, nullnull);  
  50.   
  51.             CodeNamespace aNamespace = new CodeNamespace();  
  52.             CodeCompileUnit unit = new CodeCompileUnit();  
  53.             unit.Namespaces.Add(aNamespace);  
  54.   
  55.             ServiceDescriptionImportWarnings aW = importer.Import(aNamespace, unit);  
  56.             CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");  
  57.   
  58.             CompilerParameters para = new CompilerParameters();  
  59.             para.GenerateExecutable = false;  
  60.             para.GenerateInMemory = true;  
  61.             para.ReferencedAssemblies.Add("System.dll");  
  62.             para.ReferencedAssemblies.Add("System.XML.dll");  
  63.             para.ReferencedAssemblies.Add("System.Web.Services.dll");  
  64.             para.ReferencedAssemblies.Add("System.Data.dll");  
  65.   
  66.             CompilerResults result = provider.CompileAssemblyFromDom(para, unit);  
  67.   
  68.             if (!result.Errors.HasErrors)  
  69.             {  
  70.                 Assembly asm = result.CompiledAssembly;  
  71.                 Type t = asm.GetType(className,true,true);  
  72.                 object obj =  Activator.CreateInstance(t);  
  73.                 ((System.Web.Services.Protocols.WebClientProtocol)(obj)).Url = wsdlURL;//预防端口影射导致的端口不一致。  
  74.                 return obj;  
  75.             }  
  76.             else  
  77.                 throw new Exception("WebService 动态编译错误。");  
  78.   
  79.         }  
  80.   
  81.         public static T GetWrapper<T>(object obj) where T : class  
  82.         {  
  83.             if (obj == null)  
  84.                 return null;  
  85.             return GetWrapperCore<T>(obj) as T;  
  86.         }  
  87.   
  88.         private static T GetWrapperCore<T>(object obj) where T : class  
  89.         {  
  90.             Type t = typeof(T);  
  91.             if (!t.IsInterface)  
  92.                 return obj as T;  
  93.             Type wrapperType = new WrapperHelper<T>(obj).GetWrapperType();  
  94.             if (wrapperType == null)  
  95.                 return null;  
  96.             object result = Activator.CreateInstance(wrapperType, obj);  
  97.             return result as T;  
  98.         }  
  99.   
  100.         
  101.     }  
  102.      
  103.   
  104.      
  105.     internal sealed class InterfaceNotImplementedException  
  106.         : Exception  
  107.     {  
  108.         public InterfaceNotImplementedException() { }  
  109.     }  
  110.   
  111.     internal class WrapperHelper<T> where T : class  
  112.     {  
  113.         #region Consts  
  114.         private const TypeAttributes TYPE_ATTRIBUTES =  
  115.            TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Serializable;  
  116.         private const FieldAttributes FIELD_ATTRIBUTES =  
  117.             FieldAttributes.Private;  
  118.         private const MethodAttributes METHOD_ATTRIBUTES =  
  119.             MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.HideBySig;  
  120.         #endregion  
  121.         #region Fields  
  122.         private object _obj;  
  123.         private Type _objType;  
  124.         private Type _interfaceType;  
  125.         private TypeBuilder _type;  
  126.         private FieldBuilder _field;  
  127.         #endregion  
  128.         #region Ctors  
  129.         public WrapperHelper(object obj)  
  130.         {  
  131.             _obj = obj;  
  132.             _objType = obj.GetType();  
  133.             _interfaceType = typeof(T);  
  134.         }  
  135.         #endregion  
  136.         #region Private Methods  
  137.         private void PrepareType()  
  138.         {  
  139.             AssemblyName myAssemblyName = new AssemblyName();  
  140.             myAssemblyName.Name = RandomName;  
  141.             AssemblyBuilder myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(  
  142.                 myAssemblyName, AssemblyBuilderAccess.RunAndSave);  
  143.             ModuleBuilder myModule = myAssembly.DefineDynamicModule(RandomName, true);  
  144.             _type = myModule.DefineType(RandomName,  
  145.                 TYPE_ATTRIBUTES, typeof(object), new Type[] { _interfaceType });  
  146.         }  
  147.         private void PrepareField()  
  148.         {  
  149.             _field = _type.DefineField("_source", _interfaceType, FIELD_ATTRIBUTES);  
  150.         }  
  151.         private void PrepareCtor()  
  152.         {  
  153.             Type[] myConstructorArgs = new Type[] { _objType };  
  154.             ConstructorBuilder myConstructor = _type.DefineConstructor(  
  155.                 MethodAttributes.Public, CallingConventions.Standard, myConstructorArgs);  
  156.             ILGenerator myConstructorIL = myConstructor.GetILGenerator();  
  157.             myConstructorIL.Emit(OpCodes.Ldarg_0);  
  158.             ConstructorInfo mySuperConstructor = typeof(object).GetConstructor(new Type[0]);  
  159.             myConstructorIL.Emit(OpCodes.Call, mySuperConstructor);  
  160.             myConstructorIL.Emit(OpCodes.Ldarg_0);  
  161.             myConstructorIL.Emit(OpCodes.Ldarg_1);  
  162.             myConstructorIL.Emit(OpCodes.Stfld, _field);  
  163.             myConstructorIL.Emit(OpCodes.Ret);  
  164.         }  
  165.         private void PrepareMethods()  
  166.         {  
  167.             foreach (MethodInfo mi in _interfaceType.GetMethods())  
  168.                 GenMethod(mi);  
  169.         }  
  170.         private MethodBuilder GenMethod(MethodInfo mi)  
  171.         {  
  172.             MethodBuilder result;  
  173.             Type[] paramTypes;  
  174.             ILGenerator ilGen;  
  175.             MethodInfo implMi = FindImplementedMethod(mi);  
  176.             paramTypes = GetParameterTypes(mi.GetParameters());  
  177.             result = _type.DefineMethod(mi.Name, METHOD_ATTRIBUTES, CallingConventions.Standard, mi.ReturnType, paramTypes);  
  178.             ilGen = result.GetILGenerator();  
  179.             if (mi.ReturnType != typeof(void))  
  180.                 ilGen.DeclareLocal(_objType);  
  181.             ilGen.Emit(OpCodes.Ldarg_0);  
  182.             ilGen.Emit(OpCodes.Ldfld, _field);  
  183.             for (int i = 0; i < paramTypes.Length; i++)  
  184.             {  
  185.                 if (i == 0)  
  186.                     ilGen.Emit(OpCodes.Ldarg_1);  
  187.                 else if (i == 1)  
  188.                     ilGen.Emit(OpCodes.Ldarg_2);  
  189.                 else if (i == 2)  
  190.                     ilGen.Emit(OpCodes.Ldarg_3);  
  191.                 else  
  192.                     ilGen.Emit(OpCodes.Ldarg_S, i + 1);  
  193.             }  
  194.             ilGen.Emit(OpCodes.Callvirt, implMi);  
  195.             if (mi.ReturnType != typeof(void))  
  196.             {  
  197.                 ilGen.Emit(OpCodes.Stloc_0);  
  198.                 ilGen.Emit(OpCodes.Ldloc_0);  
  199.             }  
  200.             ilGen.Emit(OpCodes.Ret);  
  201.             return result;  
  202.         }  
  203.         private void PrepareProperties()  
  204.         {  
  205.             foreach (PropertyInfo pi in _interfaceType.GetProperties())  
  206.                 GenProperty(pi);  
  207.         }  
  208.         private void GenProperty(PropertyInfo pi)  
  209.         {  
  210.             Type[] paramTypes = GetParameterTypes(pi.GetIndexParameters());  
  211.             MethodBuilder mb;  
  212.             PropertyBuilder pb = _type.DefineProperty(  
  213.                 pi.Name, pi.Attributes, pi.PropertyType, paramTypes);  
  214.             if (pi.CanRead)  
  215.             {  
  216.                 mb = GenMethod(pi.GetGetMethod());  
  217.                 pb.SetGetMethod(mb);  
  218.             }  
  219.             if (pi.CanWrite)  
  220.             {  
  221.                 mb = GenMethod(pi.GetSetMethod());  
  222.                 pb.SetSetMethod(mb);  
  223.             }  
  224.         }  
  225.         private void PrepareEvents()  
  226.         {  
  227.             foreach (EventInfo ei in _interfaceType.GetEvents())  
  228.                 GenEvent(ei);  
  229.         }  
  230.         private void GenEvent(EventInfo pi)  
  231.         {  
  232.             MethodBuilder mb;  
  233.             EventBuilder eb = _type.DefineEvent(  
  234.                 pi.Name, pi.Attributes, pi.EventHandlerType);  
  235.             mb = GenMethod(pi.GetAddMethod());  
  236.             eb.SetAddOnMethod(mb);  
  237.             mb = GenMethod(pi.GetRemoveMethod());  
  238.             eb.SetRemoveOnMethod(mb);  
  239.         }  
  240.         private MethodInfo FindImplementedMethod(MethodInfo mi)  
  241.         {  
  242.             MethodInfo result;  
  243.             result = _objType.GetMethod(mi.Name,  
  244.                 BindingFlags.Instance | BindingFlags.Public,  
  245.                 null, CallingConventions.Standard,  
  246.                 GetParameterTypes(mi.GetParameters()), null);  
  247.             if (result == null || result.ReturnType != mi.ReturnType)  
  248.                 throw new InterfaceNotImplementedException();  
  249.             return result;  
  250.         }  
  251.         #endregion  
  252.         #region Public Members  
  253.         public Type GetWrapperType()  
  254.         {  
  255.             try  
  256.             {  
  257.                 PrepareType();  
  258.                 PrepareField();  
  259.                 PrepareCtor();  
  260.                 PrepareMethods();  
  261.                 PrepareProperties();  
  262.                 PrepareEvents();  
  263.             }  
  264.             catch (InterfaceNotImplementedException)  
  265.             {  
  266.                 return null;  
  267.             }  
  268.             return _type.CreateType();  
  269.         }  
  270.         #endregion  
  271.         #region Static Members  
  272.         private static string RandomName  
  273.         {  
  274.             get { return GetRandomName(10); }  
  275.         }  
  276.         private static string GetRandomName(int count)  
  277.         {  
  278.             Random r = new Random();  
  279.             byte[] b = new byte[count];  
  280.             r.NextBytes(b);  
  281.             string result = Convert.ToBase64String(b);  
  282.             result = result.Replace('=''_').Replace('/''_').Replace('+''_');  
  283.             return result;  
  284.         }  
  285.         private static Type[] GetParameterTypes(ParameterInfo[] pis)  
  286.         {  
  287.             Type[] result = new Type[pis.Length];  
  288.             for (int i = 0; i < pis.Length; i++)  
  289.                 result[i] = pis[i].ParameterType;  
  290.             return result;  
  291.         }  
  292.         #endregion  
  293.     }  
  294.      
  295. }  

 

实际使用代码

            string wsdl = @"http://localhost/FSQS_WebService/Service.asmx?WSDL ";
            ITableWritor obj = DynWebService.GetWebServiceInterface<ITableWritor>(wsdl, "Service");
            string info = obj.TestConnection();

其中ITableWritor 是如下接口

 

 public interface ITableWritor
    {
        void UpdataTable(string clientID, string targetTableName, string srcName, DataTable sourceContent);
        string UpdataFile(string clientID,string targetTableName,string srcname,string bufferFilePath,int type);
        string TestConnection();
    }

其中"Service" 是asmx文件中对应的类的类名。类"Service"上可以显示实现ITableWritor接口。也可以仅仅包含接口所有的同名同参数,同返回值得的函数、属性。(事件应该是无效的。呵呵)

posted @ 2010-12-01 14:17  SillyProgrammer  阅读(360)  评论(0)    收藏  举报