我想创建一个代理类,支持针对基于REST的服务的异步操作。
为了便于讨论,我们假设我有一项服务IService
:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet(UriTemplate = "{a}/{b}")]
void Action(string a, string b);
}
我可以使用:
轻松创建同步代理类class Client: ClientBase<IService>, IService
{
public void Action(string a, string b)
{
Channel.Action(a, b);
}
}
(此技术来自此article)
是否有类似的直接方式使代理支持异步操作(BeginAction
/ EndAction
或ActionAsync
模式)?或者是手动滚动自己的最佳做法?
请注意,我无法在Visual Studio中添加服务引用,因为没有可用的元数据。
答案 0 :(得分:3)
如果将操作合同替换为相应的Begin / End对,则它也适用于基于REST的合同。您甚至可以在客户端上具有两个同步和异步版本的操作(但在这种情况下,您只需要在同步版本上具有[WebGet]属性。)
public class StackOverflow_6846215
{
[ServiceContract(Name = "ITest")]
public interface ITest
{
[OperationContract]
[WebGet]
int Add(int x, int y);
}
[ServiceContract(Name = "ITest")]
public interface ITestClient
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state);
int EndAdd(IAsyncResult asyncResult);
[OperationContract]
[WebGet]
int Add(int x, int y);
}
public class Client : ClientBase<ITestClient>, ITestClient
{
public Client(string baseAddress)
:base(new WebHttpBinding(), new EndpointAddress(baseAddress))
{
this.Endpoint.Behaviors.Add(new WebHttpBehavior());
}
public IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state)
{
return this.Channel.BeginAdd(x, y, callback, state);
}
public int EndAdd(IAsyncResult asyncResult)
{
return this.Channel.EndAdd(asyncResult);
}
public int Add(int x, int y)
{
return this.Channel.Add(x, y);
}
}
public class Service : ITest
{
public int Add(int x, int y)
{
return x + y;
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
host.Open();
Console.WriteLine("Host opened");
Client client = new Client(baseAddress);
Console.WriteLine("Sync result: {0}", client.Add(66, 77));
client.BeginAdd(44, 55, delegate(IAsyncResult ar)
{
int result = client.EndAdd(ar);
Console.WriteLine("Async result: {0}", result);
}, null);
Console.WriteLine("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}