假设我有一个ASMX Web服务MyService。该服务有一个方法MyMethod。我可以在服务器端执行MyMethod,如下所示:
MyService service = new MyService();
service.MyMethod();
我需要做类似的事情,直到运行时才知道服务和方法。
我认为反思是解决这个问题的方法。不幸的是,我很难让它发挥作用。当我执行此代码时:
Type.GetType("MyService", true);
它抛出了这个错误:
无法从程序集“App_Web__ktsp_r0,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null”加载“MyService”类型。
任何指导都将不胜感激。
答案 0 :(得分: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()
答案 1 :(得分:2)
//试试这个 - >
Type t = System.Web.Compilation.BuildManager.GetType("MyServiceClass", true);
object act = Activator.CreateInstance(t);
object o = t.GetMethod("hello").Invoke(act, null);
答案 2 :(得分:1)
虽然我不知道为什么Reflection不适合你(我假设编译器可能正在从你的[WebService]
注释中创建一个新类),这里有一些建议可以解决你的问题:
简单,简洁地保持您的WebService:Facade Pattern的实现。
使您的服务委托计算到实现类,该实现类应该可以通过Reflection轻松调用。这样,您的WebService类只是系统的前端 - 您甚至可以添加电子邮件处理程序,XML-RPC前端等,因为您的逻辑没有耦合到WebService,而是耦合到实际的业务层对象。
将WebService类视为架构中的UI层对象。
答案 3 :(得分: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” - 您必须检查控件的代码才能确定。
答案 4 :(得分:0)
@Kibbee:我需要避免HTTP性能损失。它不会是远程调用,因此所有这些增加的开销应该是不必要的。
这适用于需要针对任意服务/方法执行的a server control,与Web服务本身的实现方式正交。
答案 5 :(得分: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();
答案 6 :(得分:0)
@Radu:我能够创建一个实例,然后调用该方法。例如,如果我有这个ASMX:
[WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [ScriptService] public class MyService : System.Web.Services.WebService { [WebMethod] public string HelloWorld() { return "Hello World"; } }
我可以从ASPX页面的代码隐藏中调用它,如下所示:
MyService service = new MyService(); Response.Write(service.HelloWorld());
你是说这不行吗?
答案 7 :(得分:0)
我回头看了一下这个问题,我认为你所面临的是ASMX代码将被构建到一个带有随机名称的DLL中,作为站点动态编译的一部分。默认情况下,查找类型的代码只搜索自己的程序集(另一个App_Code DLL,通过您收到的错误的外观)和核心库。您可以为GetType()提供特定的程序集引用“TypeName,AssemblyName”,但在自动生成的程序集的情况下,这是不可能的,每次重新编译后都会有新名称。
解决方案......我之前没有做过这个,但我相信你应该可以使用这样的东西:
System.Web.Compilation.BuildManager.GetType("MyService", true)
因为BuildManager知道它创建的DLL并知道在哪里查看。
我想这与Web服务没有关系,但如果它是你自己的代码,那么Daren对Facade模式是正确的。