- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在下面有这些调用一些 SOAP Web 服务的方法,它们都来自同一个提供商,因此它们都具有相同的方法/调用/等等。我正在寻找一种更面向对象/抽象的方式来调用这些方法而无需编写那么多方法?理想情况下,我希望每个方法都有一个 -> GetClaim()、AddClaim()、SearchClaim()、RemoveClaim() 等。
问题 - 我是否应该传递特定于服务的参数以使方法更通用,通过消除 15 个其他方法都是这样,还是有更好的更 oop/抽象方法?有人可以给我举个例子吗?
// ex. how can I make these two methods 1?
public async void ClaimSearchForWRG(string url, string userName, string password) {
var client = new WebServiceWRGClient();
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
var endpoint = new EndpointAddress(url);
var channelFactory = new ChannelFactory<WebServiceWRG>(binding, endpoint);
var webService = channelFactory.CreateChannel();
var user = new User();
user.UserName = await webService.EncryptValueAsync(userName);
user.Password = await webService.EncryptValueAsync(password);
var response = await client.ClaimSearchAsync(user, "", "", 12345, statuscode.NotSet, "");
}
// another call (same provider) with the same call -> ClaimSearchAsync()
public async void ClaimSearchForAWI(string url, string userName, string password) {
var client = new WebServiceAWIClient();
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
var endpoint = new EndpointAddress(url);
var channelFactory = new ChannelFactory<WebServiceAWI>(binding, endpoint);
var webService = channelFactory.CreateChannel();
var user = new ArmUser();
user.UserName = await webService.EncryptValueAsync(userName);
user.Password = await webService.EncryptValueAsync(password);
var response = await client.ClaimSearchAsync(user, "", "", 12345, ArmStatuscode.NotSet, "");
}
// then we have 15 other web service calls from the same provider for ClaimSearchAsync()
// then we have 15 more calls for ClaimGetAsync()
// then we have 15 more calls for AddClaimAsync()
// then we have 15 more calls for RemoveClaimAsync()
// etc, etc, etc
已更新 在尝试使用下面的代码使事情变得更通用(以消除冗余)之后,我在代码中遇到了一些错误。特别是与编译器找不到与我传递给方法的通用实体关联的属性有关。前任。找不到 user.Username -> 错误消息说“‘TTwo’不包含‘UserName’的定义”
public class Test {
public void TestWebService() {
var ws = new WebService<WebServiceWRG>();
ws.SearchClaim(new WebServiceWRGClient(), new GraceUser(),
"https://trustonline.delawarecpf.com/tows/webservicewrg.svc", "userName", "password");
}
}
public class WebService<T> {
public void SearchClaim<TOne, TTwo>(TOne entity1, TTwo entity2, string url, string userName, string password)
where TOne : class
where TTwo : class
{
var client = entity1;
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
var endpoint = new EndpointAddress(url);
var channelFactory = new ChannelFactory<T>(binding, endpoint);
var webService = channelFactory.CreateChannel();
var user = entity2;
user.UserName = webService.EncryptValue(userName);
user.Password = webService.EncryptValue(password);
var response = client.ClaimSearch(user, "", "", 12345, GraceStatuscode.NotSet, "");
}
}
已更新 我被要求展示“ClaimSearchAsync”的作用或它是什么。我从 dotnet 生成的 Web 服务引用文件中复制了这个
System.Threading.Tasks.Task<GRACE_GRACES.WebServiceResult> ClaimSearchAsync(GRACE_GRACES.User user, string ssn, string lastname, int claimnumber, GRACE_GRACES.statuscode statuscode, string assignedto);
因为这是一个网络服务,所以没有任何方法或代码可以说明它的作用。
最佳答案
所提供的示例方法都违反了单一职责原则 (SRP) 和关注点分离 (SoC),因此我开始尝试使它们更通用。
服务和服务客户端的创建应该抽象出来成为他们自己的关注点
例如,可以通过通用工厂抽象创建 Web 服务
public interface IWebServiceFactory {
TWebService Create<TWebService>(string uri);
}
以及使用提供的 URL 封装 channel 工厂创建的简单实现。
public class ServiceFactory : IWebServiceFactory {
public TWebService Create<TWebService>(string url) {
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport) {
MaxReceivedMessageSize = Int32.MaxValue,
MaxBufferSize = Int32.MaxValue
};
var endpoint = new EndpointAddress(url);
var channelFactory = new ChannelFactory<TWebService>(binding, endpoint);
TWebService webService = channelFactory.CreateChannel();
return webService;
}
}
服务客户的创建也可以抽象出来成为它自己的关注点。
public interface IClientFactory {
TClient Create<TClient>() where TClient : class, new();
}
将根据您的客户的共同定义实现。
现在,为了创建一个通用客户端,您需要从要调用的成员所涉及的类型中获取预期的通用功能。
这可以允许将约定用于预期的类型。动态表达式用于构造所应用的约定。
为 SearchClaimAsync
生成以下帮助程序
static class ExpressionHelpers {
public static Func<string, string, TUserResult> CreateUserDelegate<TUserResult>() {
var type = typeof(TUserResult);
var username = type.GetProperty("username", BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);
var password = type.GetProperty("password", BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);
//string username =>
var usernameSource = Expression.Parameter(typeof(string), "username");
//string password =>
var passwordSource = Expression.Parameter(typeof(string), "password");
// new TUser();
var user = Expression.New(type);
// new TUser() { UserName = username, Password = password }
var body = Expression.MemberInit(user, bindings: new[] {
Expression.Bind(username, usernameSource),
Expression.Bind(password, passwordSource)
});
// (string username, string password) => new TUser() { UserName = username, Password = password }
var expression = Expression.Lambda<Func<string, string, TUserResult>>(body, usernameSource, passwordSource);
return expression.Compile();
}
public static Func<TService, string, Task<string>> CreateEncryptValueDelegate<TService>() {
// (TService service, string name) => service.EncryptValueAsync(name);
var type = typeof(TService);
// TService service =>
var service = Expression.Parameter(type, "service");
// string name =>
var name = Expression.Parameter(typeof(string), "name");
// service.EncryptValueAsync(name)
var body = Expression.Call(service, type.GetMethod("EncryptValueAsync"), name);
// (TService service, string name) => service.EncryptValueAsync(name);
var expression = Expression.Lambda<Func<TService, string, Task<string>>>(body, service, name);
return expression.Compile();
}
public static Func<TClient, TUser, Task<TResponse>> CreateClaimSearchDelegate<TClient, TUser, TResponse>() {
var type = typeof(TClient);
// TClient client =>
var client = Expression.Parameter(type, "client");
// TUser user =>
var user = Expression.Parameter(typeof(TUser), "user");
var method = type.GetMethod("ClaimSearchAsync");
var enumtype = method.GetParameters()[4].ParameterType; //statuscode
var enumDefault = Activator.CreateInstance(enumtype);
var arguments = new Expression[] {
user,
Expression.Constant(string.Empty), //ssn
Expression.Constant(string.Empty), //lastname
Expression.Constant(12345), //claimnumber
Expression.Constant(enumDefault), //statuscode
Expression.Constant(string.Empty)//assignto
};
// client.ClaimSearchAsync(user, ssn: "", lastname: "", claimnumber: 12345, statuscode: default(enum), assignedto: "");
var body = Expression.Call(client, method, arguments);
// (TClient client, TUser user) => client.ClaimSearchAsync(user,....);
var expression = Expression.Lambda<Func<TClient, TUser, Task<TResponse>>>(body, client, user);
return expression.Compile();
}
}
花一些时间查看评论,以更好地了解正在做的事情。
通用网络服务可以定义如下
public class WebService<TWebServiceClient, TWebService, TUser>
where TWebService : class
where TWebServiceClient : class, new()
where TUser : class, new() {
/// <summary>
/// Create user object model
/// </summary>
private static readonly Func<string, string, TUser> createUser =
ExpressionHelpers.CreateUserDelegate<TUser>();
/// <summary>
/// Encrypt provided value using <see cref="TWebService"/>
/// </summary>
private static readonly Func<TWebService, string, Task<string>> encryptValueAsync =
ExpressionHelpers.CreateEncryptValueDelegate<TWebService>();
private readonly IWebServiceFactory serviceFactory;
private readonly IClientFactory clientFactory;
Lazy<TWebServiceClient> client;
public WebService(IWebServiceFactory serviceFactory, IClientFactory clientFactory) {
this.serviceFactory = serviceFactory ?? throw new ArgumentNullException(nameof(serviceFactory));
this.clientFactory = clientFactory ?? throw new ArgumentNullException(nameof(clientFactory));
client = new Lazy<TWebServiceClient>(() => clientFactory.Create<TWebServiceClient>());
}
public async Task<TResponse> SearchClaimAsync<TResponse>(WebServiceOptions options) {
TWebService webService = serviceFactory.Create<TWebService>(options.URL);
TUser user = createUser(
await encryptValueAsync(webService, options.UserName),
await encryptValueAsync(webService, options.Password)
);
Func<TWebServiceClient, TUser, Task<TResponse>> claimSearchAsync =
ExpressionHelpers.CreateClaimSearchDelegate<TWebServiceClient, TUser, TResponse>();
TResponse response = await claimSearchAsync.Invoke(client.Value, user);
return response;
}
//...other generic members to be done
}
public class WebServiceOptions {
public string URL { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}
它自身的代码与实现问题充分分离,允许对其进行隔离测试,以确保其行为符合预期。
如以下单元测试所示
[TestClass]
public class GenericWebServiceTests {
[TestMethod]
public void Should_Create_New_WebService() {
//Arrange
var serviceFactory = Mock.Of<IWebServiceFactory>();
var clientFactory = Mock.Of<IClientFactory>();
//Act
var actual = new WebService<WebServiceWRGClient, IWebService, User1>(serviceFactory, clientFactory);
//Assert
actual.Should().NotBeNull();
}
[TestMethod]
public async Task Should_ClaimSearchAsync() {
//Arrange
var service = Mock.Of<IWebService>();
Mock.Get(service)
.Setup(_ => _.EncryptValueAsync(It.IsAny<string>()))
.ReturnsAsync((string s) => s);
var serviceFactory = Mock.Of<IWebServiceFactory>();
Mock.Get(serviceFactory)
.Setup(_ => _.Create<IWebService>(It.IsAny<string>()))
.Returns(service);
var clientFactory = Mock.Of<IClientFactory>();
Mock.Get(clientFactory)
.Setup(_ => _.Create<WebServiceWRGClient>())
.Returns(() => new WebServiceWRGClient());
string url = "url";
string username = "username";
string password = "password";
var options = new WebServiceOptions {
URL = url,
UserName = username,
Password = password
};
var webService = new WebService<WebServiceWRGClient, IWebService, User1>(serviceFactory, clientFactory);
//Act
var actual = await webService.SearchClaimAsync<WebServiceResult>(options);
//Assert
//Mock.Get(serviceFactory).Verify(_ => _.Create<IService1>(url));
//Mock.Get(service).Verify(_ => _.EncryptValue(username));
//Mock.Get(service).Verify(_ => _.EncryptValue(password));
//Mock.Get(clientFactory).Verify(_ => _.Create<Client1>());
actual.Should().NotBeNull();
}
#region Support
public class User1 {
public string UserName { get; set; }
public string Password { get; set; }
}
public class User2 {
public string UserName { get; set; }
public string Password { get; set; }
}
public class WebServiceWRGClient {
public Task<WebServiceResult> ClaimSearchAsync(User1 user, string ssn, string lastname, int claimnumber, statuscode statuscode, string assignedto) {
return Task.FromResult(new WebServiceResult());
}
}
public enum statuscode {
NotSet = 0,
}
public class Client2 { }
public interface IWebService {
Task<string> EncryptValueAsync(string value);
}
public interface IService2 {
Task<string> EncryptValueAsync(string value);
}
public class Service1 : IWebService {
public Task<string> EncryptValueAsync(string value) {
return Task.FromResult(value);
}
}
public class WebServiceResult {
}
#endregion
}
这应该足以让您开始审查其他成员以使其成为通用的。上面提供的代码已经过测试,并根据原始问题中提供的内容按预期工作。
请注意,根据要重构的成员数量,这似乎是一项艰巨的任务。您应该花一些时间来确保这些努力是值得的。
关于c# - 如何使多个 SOAP Web 服务调用通用以减少冗余?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58088668/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!