如何将此事件展开为可观察序列?

时间:2015-08-30 23:45:52

标签: c# system.reactive observable

好吧,就在我认为我已经掌握了一些东西的时候,我又被抛出了另一条曲线。

我试图创建一个可观察的序列而不是这样做:

((Outlook.MAPIFolderEvents_12_Event)calendarFolder).BeforeItemMove += 
   Calendar_BeforeItemMove;

private void Calendar_BeforeItemMove(
    object item, 
    Outlook.MAPIFolder destFolder, 
    ref bool cancel){ /*...*/ }

我尝试使用Observable.FromEventPattern<TDelegate, TEventArgs> (Func<EventHandler<TEventArgs>, TDelegate>, Action<TDelegate>, Action<TDelegate>)方法,但由于所需的参数,我很难取得成功。我能来的最接近的是:

var itemBeforeMovedObservable = Observable
    .FromEvent<Outlook.MAPIFolderEvents_12_BeforeItemMoveEventHandler, object>(handler =>
    {
       Outlook.MAPIFolderEvents_12_BeforeItemMoveEventHandler bimEventHandler =
       (obj, f, ref cx) =>  // <-- Cannot resolve symbol 'cx'; Identifier expected
       {
          handler(obj); // <-- shouldn't this have the other parameters as well?
       };
       return bimEventHandler;
    },
    h => ((Outlook.MAPIFolderEvents_12_Event)calendarFolder).BeforeItemMove += h,
    h => ((Outlook.MAPIFolderEvents_12_Event)calendarFolder).BeforeItemMove -= h);

提前感谢任何指导。

1 个答案:

答案 0 :(得分:0)

我真的没有办法测试这个,但我会说你可能最好把它包装成一个运营商:

//Because that naming is ridiculous
using ItemMoveEventHandler = Outlook.MAPIFolderEvents_12_BeforeItemMoveEventHandler; 
using ItemMoveEvent = Outlook.MAPIFolderEvents_12_Event;

//Used to wrap multiple arguments into a single object
public class MyMoveEventArgs {
  public MyMoveEventArgs(Object item, MAPIFolder folder) {
    this.Item = item;
    this.Folder = folder;
  }

  public Object Item {get; private set;}
  public MAPIFolder Folder {get; private set;}
}

//Create an extension method
public static IObservable<MyMoveEventArgs> BeforeMoveObservable(
  this ItemMoveEvent folder, 
  Func<object, MAPIFolder, bool> shouldCancel) {

    return Observable.FromEvent<ItemMoveEventHandler, 
                              MoveEventArgs>
                    //Use the conversion overload
                    (emit => new ItemMoveEventHandler(
                          //The compiler seems to complain about cancel
                          //being implicit, so explicitly declare your params
                          (object item, MAPIFolder f, out bool cancel) => 
                          {
                            //cancel needs to be set somewhere in the body
                            if (!(cancel = shouldCancel(item, f)) {
                             emit(new MyMoveEventArgs(item, f));
                            }
                          }
                    },
                    h => folder.BeforeItemMove += h,
                    h => folder.BeforeItemMove -= h);

}

然后你应该可以这样使用它(未经测试):

calendarFolder.BeforeMoveObservable((obj, folder => /*Return if the event should be cancelled or not*/)
.Subscribe(x => /*Only reach here if the move was successful*/);