有谁知道如何使用Reactive Extensions调用RIA InvokeOperation?一旦调用全部完成,我需要处理来自Silverlight中几个异步调用的一些数据。在我的测试中,我将一些字符串与查询结果相结合,现在需要添加来自调用RIA域服务调用方法的结果,并且卡住了。
我在RIA域服务端的简单测试功能(完成非RX风格)如下所示:
[Invoke]
public string DomainServiceFunction()
{
return "hello";
}
在客户端,这个老派的代码调用了这个方法,并且是我想用RX实现的部分:
private void CallDomainServiceFunction(object sender, RoutedEventArgs e)
{
DomainService1 DomainContext = new DomainService1();
InvokeOperation invokeOp = DomainContext.DomainServiceFunction(OnInvokeCompleted, null);
}
private void OnInvokeCompleted(InvokeOperation invOp)
{
Debug.WriteLine(invOp.Value);//This prints "hello".
}
我编写了一些测试代码,它结合了来自多个来源的数据(这也是我想要添加RIA InvokeOperation调用的地方)。它是由几个字符串和一个查询返回的实体组成的元组:
private void PrintProperty1()
{
GISDomainContext DomainContext = new GISDomainContext();
//Query the database to get information for a property using the folio number.
var loadProperty = from loadOperation in DomainContextExtensions
.LoadAsync(DomainContext, DomainContext.GetPropertyNoOwnersByFolioQuery("19401006.000"))
select loadOperation;
//Zip up the property entity with a string for testing purposes.
var Data = Observable.Return("a bit of text ")
.Zip((Observable.Return("some more text")
.Zip(loadProperty, (a, b) => Tuple.Create(a, b))), (a,b) => Tuple.Create(a,b));
//Add a bit more stuff just to show it can be done.
//THIS IS WHERE I WOULD ALSO ZIP WITH THE VALUE RETURNED FROM AN InvokeOperation.
Data.Subscribe
(
//When all the required data are prepared then proceed...
r => //On Next
{
Debug.WriteLine("OnNext: " + r.Item1 + ", " + r.Item2.Item1 + ", " + r.Item2.Item2.Entities.First().folio.ToString());
//results: "OnNext: a bit of text , some more text, 19401006.000"
//At this point the data are all now available for further processing.
},
r => //On Error
{
Debug.WriteLine("Error in PrintProperty1: " + r.ToString());
},
() =>//On Completed
{
Debug.WriteLine("Completed PrintProperty1");
}
);
}
我怀疑FromAsyncPattern
是关键,但显然Silverlight隐藏了FromAsyncPattern
期望作为参数的开始/结束调用
引自here:
“Silverlight的一个重要说明!
Silverlight的网络服务 生成的客户端代码做了一些有点烦人的事 - 它隐藏起来了 BeginXXXX / EndXXXX调用,大概是为了制作Intellisense 清洁器。然而,他们没有消失,你可以让他们回来的方式是 通过将MyCoolServiceClient对象强制转换为其底层接口 (即LanguageServiceClient对象已生成 它实现的ILanguageServiceClient接口)“
有什么建议吗?
答案 0 :(得分:1)
实际上,Silverlight并没有隐藏任何东西。这些方法不存在于由RIA服务工具生成的DomainContext
派生代理上。
但是这是一个将Invoke
操作包装到IObservable
的扩展方法:
public static class DomainContextExtensions
{
// The method takes in an invoke operation proxy method delegate
// and returns an observable sequence factory
public static Func<T1, IObservable<TResult>> FromInvokeOperation<T1, TResult>
(Func<T1, Action<InvokeOperation<TResult>>, object, InvokeOperation<TResult>> operationDelegate)
{
Contract.Requires<ArgumentNullException>(operationDelegate != null, "operationDelegate");
Contract.Ensures(Contract.Result<Func<T1, IObservable<TResult>>>() != null);
return x1 =>
{
// the subject is a storage for the result.
var subject = new AsyncSubject<TResult>();
try
{
var invokeOperation = operationDelegate(x1, operation =>
{
// handle operation results
if (operation.IsCanceled)
{
return;
}
if (operation.HasError)
{
subject.OnError(operation.Error);
operation.MarkErrorAsHandled();
return;
}
Contract.Assume(operation.IsComplete);
subject.OnNext(operation.Value);
subject.OnCompleted();
}, null);
// create the operation cancellation object
var invokeOperationCancellation = Disposable.Create(() =>
{
// need to check if the operation has completed before the subscription is disposed
if (!invokeOperation.IsComplete && invokeOperation.CanCancel)
invokeOperation.Cancel(); // this might abort the web call to save bandwidth
});
// construct a new observable that adds invoke operation cancellation upon dispose
return Observable.Create<TResult>(obs => new CompositeDisposable(invokeOperationCancellation, subject.Subscribe(obs)));
}
catch (Exception ex)
{
return Observable.Create<TResult>(obs =>
{
obs.OnError(ex);
return Disposable.Empty;
});
}
};
}
}
这应该有用,虽然我没有测试过。
用法:
var context = ... // get your DomainContext
var param = ... // operation parameter
// This will create the observable:
var o = DomainContextExtensions.FromInvokeOperation</*Parameter type goes here*/, /*Result type goes here*/>(context.YourOperationMethod)(param);
o.Subscribe(...); // subscribe as you wish or build a query
您必须编写其他方法来支持具有不同数量参数的调用操作。