c#动态web服务调用返回自定义类

c#动态web服务调用返回自定义类,c#,web-services,reflection,types,C#,Web Services,Reflection,Types,我有一个类,它提供对web服务的动态调用 private System.Xml.XmlTextReader _XmlReader; private System.Web.Services.Description.ServiceDescription _ServiceDescription; private System.Web.Services.Description.ServiceDescriptionImporter _DescriptionImporter; private System.

我有一个类,它提供对web服务的动态调用

private System.Xml.XmlTextReader _XmlReader;
private System.Web.Services.Description.ServiceDescription _ServiceDescription;
private System.Web.Services.Description.ServiceDescriptionImporter _DescriptionImporter;
private System.CodeDom.CodeNamespace _CodeNamespace;
private System.CodeDom.CodeCompileUnit _CodeUnit;
private System.Web.Services.Description.ServiceDescriptionImportWarnings _ImportWarnings;
private System.CodeDom.Compiler.CodeDomProvider _Compiler;
private System.CodeDom.Compiler.CompilerParameters _Parameters;
private System.CodeDom.Compiler.CompilerResults _Results;
private System.Reflection.Assembly _WebServiceAssembly;
private string _Url;

public WebServiceInvoker(string url)
{
  _Url = url;
  System.Net.ServicePoint servicePoint = System.Net.ServicePointManager.FindServicePoint(new Uri(_Url));
  servicePoint.Expect100Continue = false;
  _XmlReader = new System.Xml.XmlTextReader(_Url);
  _ServiceDescription = System.Web.Services.Description.ServiceDescription.Read(_XmlReader);
  _DescriptionImporter = new System.Web.Services.Description.ServiceDescriptionImporter();
  _DescriptionImporter.ProtocolName = "Soap";
  _DescriptionImporter.AddServiceDescription(_ServiceDescription, null, null);
  _DescriptionImporter.Style = System.Web.Services.Description.ServiceDescriptionImportStyle.Client;
  _DescriptionImporter.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
  _CodeNamespace = new System.CodeDom.CodeNamespace();
  _CodeUnit = new System.CodeDom.CodeCompileUnit();
  _CodeUnit.Namespaces.Add(_CodeNamespace);
  _ImportWarnings = _DescriptionImporter.Import(_CodeNamespace, _CodeUnit);
  if (_ImportWarnings != 0) throw new Exception("Can not resolve registration service.");
  _Compiler = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("CSharp");
  string[] references = new string[] { "System.Web.Services.dll", "System.Xml.dll" };
  _Parameters = new System.CodeDom.Compiler.CompilerParameters(references);
  _Results = _Compiler.CompileAssemblyFromDom(_Parameters, _CodeUnit);
  foreach (System.CodeDom.Compiler.CompilerError oops in _Results.Errors) { throw new Exception("Compile Error Creating Assembly"); }
  _WebServiceAssembly = _Results.CompiledAssembly;
}

public LYSProducts.ProductObject GetProduct(string productCode)
{
  LYSProducts.ProductObject p;
  object obj = _WebServiceAssembly.CreateInstance("RegisteryService");
  Type typ = obj.GetType();
  p = (LYSProducts.ProductObject)typ.InvokeMember("GetProduct", System.Reflection.BindingFlags.InvokeMethod, null, obj, new object[] { productCode });
  return p;
}
GetProduct方法返回一个自定义类

    namespace LYSProducts
{
  [Serializable()]
  class ProductObject
  {
    public string ProductCode
    {
      get { return _ProductCode; }
      set { _ProductCode = value; }
    }
    public string ProductName
    {
      get { return _ProductName; }
      set { _ProductName = value; }
    }
    public string MajorVer
    {
      get { return _MajorVer; }
      set { _MajorVer = value; }
    }
    public string MinorVer
    {
      get { return _MinorVer; }
      set { _MinorVer = value; }
    }
private string _ProductCode;
private string _ProductName;
private string _MajorVer;
private string _MinorVer;

public ProductObject(string productCode, string productName)
{
  _ProductCode = productCode;
  _ProductName = productName;
  _MajorVer = "";
  _MinorVer = "";
}
public ProductObject(string productCode, string productName, string majorVer, string minorVer)
{
  _ProductCode = productCode;
  _ProductName = productName;
  _MajorVer = majorVer;
  _MinorVer = minorVer;
}
  }
}

代码运行良好。但是“typ.InvokeMember”方法返回了一个对象,我不知道如何将它转换为LYSProducts.ProdutcObject类。我在客户端部署了相同的类,但当我尝试强制转换时,收到“无法将'ProductObject'类型的对象转换为'LYSProducts.ProductObject'”错误。我知道服务必须为“ProductObject”类型提供一些模式,我可以使用反射从这些信息创建ProductObject,但我不知道怎么做

下面是我如何解决这个问题的。也许有人能从中得到一些帮助

public ServiceResponseBase GetProduct(string productCode)
      {
        object obj = _WebServiceAssembly.CreateInstance("RegisteryService");
        Type typ = obj.GetType();
        object o = typ.InvokeMember("GetProduct", System.Reflection.BindingFlags.InvokeMethod, null, obj, new object[] { productCode });
        return InstantiateObject<ProductResponse>(o);
      }


private T InstantiateObject<T>(object o) where T : class
      {
        Type t = o.GetType();
        object r = Activator.CreateInstance(typeof(T));
        foreach (System.Reflection.PropertyInfo p in t.GetProperties()) r.GetType().GetProperty(p.Name).SetValue(r, p.GetValue(o, null), null);
        return (T)r;
      }
公共服务响应数据库GetProduct(字符串productCode) { object obj=_WebServicesAssembly.CreateInstance(“RegisteryService”); Type typ=obj.GetType(); 对象o=typ.InvokeMember(“GetProduct”,System.Reflection.BindingFlags.InvokeMethod,null,obj,新对象[]{productCode}); 返回实例化对象(o); } 私有T实例化对象(对象o),其中T:class { 类型t=o.GetType(); objectr=Activator.CreateInstance(typeof(T)); foreach(System.Reflection.PropertyInfo p in t.GetProperties())r.GetType().GetProperty(p.Name).SetValue(r,p.GetValue(o,null),null); 返回(T)r; } ProductResponse类派生自ServiceResponseBase。

//
    /// <summary>
    /// Invokes the specified method of the named service.
    /// </summary>
    /// <by>J.BETTAIEB</by>
    /// <typeparam name="T">The expected return type.</typeparam>
    /// <param name="serviceName">The name of the service to use.</param>
    /// <param name="methodName">The name of the method to call.</param>
    /// <param name="args">The arguments to the method.</param>
    /// <returns>The return value from the web service method.</returns>
    public T InvokeMethod<T>( string serviceName, string methodName, params object[] args )
    {
        // create an instance of the specified service
        // and invoke the method
        object obj = this.webServiceAssembly.CreateInstance(serviceName);

        Type type = obj.GetType();

        return (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args);
    }
///调用命名服务的指定方法。 /// ///贝塔伊布 ///预期的返回类型。 ///要使用的服务的名称。 ///要调用的方法的名称。 ///方法的参数。 ///web服务方法的返回值。 public T InvokeMethod(字符串serviceName、字符串methodName、参数对象[]args) { //创建指定服务的实例 //并调用该方法 object obj=this.webserviceCassembly.CreateInstance(serviceName); Type Type=obj.GetType(); return(T)type.InvokeMember(methodName,BindingFlags.InvokeMethod,null,obj,args); }
如果有人想让服务URL可配置,那么您不需要跳过这些障碍,只需创建您的服务、设置URL属性并调用您的方法即可。