7

假设我有一个 ASMX Web 服务 MyService。该服务有一个方法,MyMethod。我可以在服务器端执行 MyMethod 如下:

MyService service = new MyService();
service.MyMethod();

我需要做类似的事情,直到运行时才知道服务和方法。

我假设反思是解决这个问题的方法。不幸的是,我很难让它发挥作用。当我执行此代码时:

Type.GetType("MyService", true);

它抛出这个错误:

无法从程序集“App_Web__ktsp_r0,版本=0.0.0.0,文化=中性,PublicKeyToken=null”加载类型“MyService”。

任何指导将不胜感激。

4

8 回答 8

2

我不确定这是否是最好的方法。对我来说最明显的方法是发出 HTTP 请求,并使用实际的 HTTP GET 或 POST 调用 Web 服务。使用您的方法,我不完全确定您将如何设置发送到 Web 服务的数据。我在 VB.Net 中添加了一些示例代码

Dim HTTPRequest As HttpWebRequest
Dim HTTPResponse As HttpWebResponse
Dim ResponseReader As StreamReader
Dim URL AS String
Dim ResponseText As String

URL = "http://www.example.com/MyWebSerivce/MyMethod?arg1=A&arg2=B"

HTTPRequest = HttpWebRequest.Create(URL)
HTTPRequest.Method = "GET"

HTTPResponse = HTTPRequest.GetResponse()

ResponseReader = New StreamReader(HTTPResponse.GetResponseStream())
ResponseText = ResponseReader.ReadToEnd()
于 2008-09-15T12:35:20.230 回答
2

// 试试这个 ->

    Type t = System.Web.Compilation.BuildManager.GetType("MyServiceClass", true);
    object act = Activator.CreateInstance(t);                
    object o = t.GetMethod("hello").Invoke(act, null);
于 2009-04-08T14:02:13.550 回答
1

虽然我不知道为什么 Reflection 在那里不起作用(我假设编译器可能正在从您的[WebService]注释创建一个新类),但这里有一些建议可以解决您的问题:

简而言之,保持您的 WebService 简单、浅薄:外观模式的实现

让您的服务将计算委托给一个实现类,该类应该可以通过反射轻松调用。这样,您的 WebService 类只是您系统的前端 - 您甚至可以添加电子邮件处理程序、XML-RPC 前端等,因为您的逻辑不与 WebService 耦合,而是与实际的业务层对象耦合。

将 WebService 类视为架构中的 UI 层对象。

于 2008-09-15T12:46:12.870 回答
1

这是一个可能有人可以扩展的快速答案。

当您使用 WSDL 模板应用程序 (WSDL.exe) 生成服务包装器时,它会构建一个 SoapHttpClientProtocol 类型的类。您也可以手动完成:

public class MyService : SoapHttpClientProtocol
{
    public MyService(string url)
    {
        this.Url = url;
        // plus set credentials, etc.
    }

    [SoapDocumentMethod("{service url}", RequestNamespace="{namespace}", ResponseNamespace="{namespace}", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    public int MyMethod(string arg1)
    {
        object[] results = this.Invoke("MyMethod", new object[] { arg1 });
        return ((int)(results[0]));
    }
}

我没有测试过这段代码,但我想它应该可以独立运行,而无需运行 WSDL 工具。

我提供的代码是调用者代码,它通过远程调用连接到 Web 服务(即使出于某种原因,您实际上并不希望它是远程的。) Invoke 方法负责将其打包为肥皂电话。如果您想通过 HTTP 绕过 Web 服务调用,@Dave Ward 的代码是正确的——只要您实际上能够引用该类。也许内部类型不是“MyService”——您必须检查控件的代码才能确定。

于 2008-09-15T13:20:27.703 回答
0

@Kibbee:我需要避免 HTTP 性能下降。它不会是远程调用,因此所有这些增加的开销都应该是不必要的。

@Daren:我绝对同意这种设计理念。这里的问题是我不会控制服务或其底层业务逻辑。

这是针对需要针对任意服务/方法执行的服务器控件,与 Web 服务本身的实现方式正交。

于 2008-09-15T12:59:24.413 回答
0

虽然我不能从你的帖子中看出:

要记住的一件事是,如果您使用反射,您需要创建一个自动生成的 Web 服务类的实例(从您的 Web 服务的 WSDL 创建的那个)。不要创建负责服务服务器端的类。

所以如果你有一个网络服务

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    public class WebService1 : System.Web.Services.WebService
    {
     ...
    }

您不能在客户端中引用该程序集并执行以下操作:

WebService1  ws = new WebService1 ();
ws.SomeMethod();
于 2008-09-15T13:09:29.460 回答
0

@Radu:我能够创建一个实例并完全像那样调用该方法。例如,如果我有这个 ASMX:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[脚本服务]
公共类 MyService : System.Web.Services.WebService
{
  [网络方法]
  公共字符串 HelloWorld()
  {
    返回“你好世界”;
  }
}

我可以像这样从 ASPX 页面的代码隐藏中调用它:

我的服务服务 = 新的我的服务();
Response.Write(service.HelloWorld());

你说那不应该?

于 2008-09-15T13:18:00.877 回答
0

我回顾了这个问题,我认为您面临的是 ASMX 代码将被构建到一个具有随机名称的 DLL 中,作为您站点动态编译的一部分。默认情况下,您查找类型的代码将仅搜索其自己的程序集(另一个 App_Code DLL,根据您收到的错误的外观)和核心库。您可以向 GetType() 提供特定的程序集引用“TypeName,AssemblyName”,但对于自动生成的程序集(每次重新编译后都有新名称),这是不可能的。

解决方案....我以前没有自己做过,但我相信你应该能够使用这样的东西:

System.Web.Compilation.BuildManager.GetType("MyService", true)

因为 BuildManager 知道它创建的 DLL 并且知道在哪里查找。

我想这确实与 Web 服务无关,但如果是您自己的代码,Daren 对 Facade 模式的看法是正确的。

于 2008-09-17T21:02:26.123 回答