上下文
当前,我正在使用.NET Core创建用C#编写的提取加载和转换(ETL)应用程序。 ETL应用程序的源代码是Soap Web服务,其中包含多种方法。每个实体(员工,公司等)和检索方式(ByKey,ByQuery等)都有自己的Soap Web服务方法。例如,如果我要通过执行查询来检索实体“ Employee”,则将调用GetEmployeeByQuery
方法。所有方法都返回带有XML的字符串。
Visual Studio通过其WSDL文件(通过dotnet-svcutil间接生成)生成了该Web服务的代理类。不幸的是,为该服务生成的代理类似乎是根据消息契约模式生成的。这意味着代理方法GetEmployeeByQuery
返回GetEmployeeByQueryResponse
子类,该子类具有包含Body
子类的字段GetEmployeesByQueryResponseBody
。实际结果位于GetEmployeeByQueryResponseBody
名称为GetEmployeeByQueryResult
的字符串字段中。
尝试调整代码生成,产生不遵循消息契约模式的代理类的尝试并未取得成果。调整'ConnectedService.json'文件中的选项GenerateMessageContract
或直接使用dotnet-svcutil.exe工具都不会导致生成的代码发生任何变化。
注意:在.NET Framework中,生成的代码不遵循消息契约模式。
目标
理想情况下,ETL应用程序能够通过反射并基于其配置来调用Soap Webservice方法。该配置包含要调用的方法和参数,并且通过某些工厂,这导致可以在应用程序中的其他位置调用Delegate(或类似MethodInfo对象之类的东西)。此委托应该是通用的,不应与任何特定实体绑定。
由于消息协定(部分)类'... Response'和'... ResponseBody',使动态调用生成的Soap Webservice方法变得相当复杂。而不是为每个生成的代理方法都具有最相似的方法签名(参数和返回类型始终为字符串)。现在,对于每个生成的代理方法以及每个实体,我都有一个不同的方法签名。
我希望对多个方法使用相同的委托的原因是,每个实体类型执行的动作实际上是相同的。我不想以每个实体独立的方式来编写代码,而不是为每个单独的实体编写代码。
问题
我当前的解决方案是创建一个独立于实体的委托。为了确保委托具有相同的方法签名,在生成的类上放置了一个接口。生成的...Response
和...ResponseBody
类是局部的。我将这些类扩展到另一个文件中,并在它们上实现一个接口。无论使用哪种实体类型,该界面都使我能够检索结果。
接口
public interface IMessageResult<T>
{
T GetResult();
}
接口实现
public partial class GetUDICByQueryResponse : IMessageResult<string>
{
public string GetResult()
{
return Body.GetUDICByQueryResult;
}
}
很遗憾,我无法成功创建委托。每当我尝试通过Delegate.CreateDelegate创建委托时,都会出现以下错误:
Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
当我使用具体的类而不是接口时,不会发生这种情况。
用于创建代表的助手
public static TMethodSignature GetLocalMethod<TMethodSignature>(object classInstance, string methodName)
where TMethodSignature : class
{
Type methodSignature = typeof(TMethodSignature);
TMethodSignature method = Delegate.CreateDelegate(
methodSignature,
classInstance,
methodName) as TMethodSignature;
if (method == null)
throw new InvalidCastException($"Method {methodName} could not be cast into a delegate. The given method signature could not be found.");
return method;
}
调用助手方法
var soapMethod = ReflectionUtils.GetLocalMethod<Func<string, string, string, string, Task<IMessageResult<string>>>>(Service, parameters.MethodName);
任何帮助将不胜感激!
答案 0 :(得分:0)
经过一段闲暇时间,我终于明白了为什么它不起作用(一个愚蠢的错误)。我尝试检索的Soap Webservice方法具有仅使用特定(响应)类Type定义的签名。没有定义使用接口定义响应的方法。因此,Delegate.CreateDelegate()方法无法绑定目标方法。
我面临的更大的问题仍然是如何通过应用程序配置的反射来调用Soap Webservice方法。