Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用反应式扩展在域服务中调用Silverlight RIA InvokeOperation?_Silverlight_System.reactive_Invoke - Fatal编程技术网

如何使用反应式扩展在域服务中调用Silverlight RIA InvokeOperation?

如何使用反应式扩展在域服务中调用Silverlight RIA InvokeOperation?,silverlight,system.reactive,invoke,Silverlight,System.reactive,Invoke,有人知道我如何使用反应式扩展调用RIA调用操作吗?一旦调用完成,我需要在Silverlight中处理来自多个异步调用的一些数据。在我的测试中,我将两个字符串与查询结果组合在一起,现在需要添加调用RIA域服务调用方法的结果,我被卡住了 我在RIA域服务端的简单测试功能(完成非RX样式)如下所示: [Invoke] public string DomainServiceFunction() { return "hello"; }

有人知道我如何使用反应式扩展调用RIA调用操作吗?一旦调用完成,我需要在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");
            }
        );
    }
我怀疑
fromsyncPattern
是关键,但显然Silverlight隐藏了
fromsyncPattern
期望作为参数的Begin/End调用

引自:

“Silverlight的重要提示

Silverlight的web服务 生成的客户端代码有点烦人——它隐藏起来了 BeginXXXX/EndXXXX调用,可能是为了实现智能感知 更干净。但是,它们没有消失,你能找回它们的方法是 通过将MyColServiceClient对象强制转换到其底层接口 (即LanguageServiceClient对象具有生成的 ILanguageServiceClient接口(它实现的)


有什么建议吗?

事实上,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;
            });
        }
      };
  }
}
公共静态类DomainContextensions
{
//该方法接受调用操作代理方法委托
//并返回一个可观察的序列工厂
来自InvokeOperation的公共静态函数
(Func operationDelegate)
{
Contract.Requires(operationDelegate!=null,“operationDelegate”);
Contract.sure(Contract.Result()!=null);
返回x1=>
{
//主题是结果的存储。
var subject=new AsyncSubject();
尝试
{
var invokeOperation=operationDelegate(x1,操作=>
{
//处理操作结果
如果(操作被取消)
{
返回;
}
if(operation.HasError)
{
subject.OnError(操作错误);
操作。MarkErrorAsHandled();
返回;
}
合同。承担(操作。完成);
subject.OnNext(operation.Value);
subject.OnCompleted();
},空);
//创建操作取消对象
var invokeOperationCancellation=Disposable.Create(()=>
{
//在释放订阅之前,需要检查操作是否已完成
如果(!invokeOperation.IsComplete&&invokeOperation.CanCancel)
invokeOperation.Cancel();//这可能会中止web调用以节省带宽
});
//构造一个新的可观察对象,在dispose时添加调用操作取消
返回Observable.Create(obs=>newcompositedisposable(invokeOperationCancellation,subject.Subscribe(obs));
}
捕获(例外情况除外)
{
返回可观察的。创建(obs=>
{
obs.OnError(ex);
返回一次性。空;
});
}
};
}
}
虽然我还没有测试过,但它应该可以工作

用法:

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
var context=…//获取您的域上下文
变量参数=…//操作参数
//这将创建可观察的:
var o=DomainContextExtensions.FromInvokeOperation(context.YourOperationMethod)(param);
o、 订阅(…);//按需订阅或生成查询

您必须编写其他方法来支持具有不同数量参数的调用操作。

非常感谢,这很有效。经过一番努力,我还让它与输入参数一起工作。@user1066012如果它仍然有趣,我已经改进了实现。现在它非常接近RX的
可观察。FromAsyncPattern
实现,支持单个参数,并且没有同步问题。如果订阅是在RIA操作刚刚完成之后处理的,那么以前的代码可能会抛出断言。如果对以前的注释有任何疑问:我的答案的当前版本(2)已经有了我在该注释中提到的代码。欢迎提出进一步建议/问题。