C# 从非标准事件创建可观察事件(无EventArgs/EventHandler)
我想为定义如下的事件创建一个可观察的事件:C# 从非标准事件创建可观察事件(无EventArgs/EventHandler),c#,.net,events,observable,system.reactive,C#,.net,Events,Observable,System.reactive,我想为定义如下的事件创建一个可观察的事件: public event Func<Exception, Task> Closed; 公共事件功能关闭; 我目前的代码是: Observable.FromEvent<Func<Exception, Task>, Unit>(h => hub.Closed += h, h=> hub.Closed -= h); Observable.FromEvent(h=>hub.Closed+=h,h=>hub
public event Func<Exception, Task> Closed;
公共事件功能关闭;
我目前的代码是:
Observable.FromEvent<Func<Exception, Task>, Unit>(h => hub.Closed += h, h=> hub.Closed -= h);
Observable.FromEvent(h=>hub.Closed+=h,h=>hub.Closed-=h);
它编译正常,但会引发以下运行时异常:
System.ArgumentException:'无法绑定到目标方法,因为
其签名或安全透明度与
委托类型为“”
我觉得我做错了。我不习惯从不遵循EventArgs模式的事件中创建可观察对象,请尝试以下操作,不要使用您想要的签名,而是尝试一些东西:
class Program
{
public delegate void ClosedEventHandler(object sender, Func<Exception, Task> e);
public ClosedEventHandler Closed { get; set; }
static void Main(string[] args)
{
Program hub = new Program();
hub.Closed = hub.SomethingToDoWhenClosed;
Observable
.FromEventPattern<ClosedEventHandler, Func<Exception, Task>>(
h => hub.Closed += h,
h => hub.Closed -= h)
.Subscribe(x =>
{
// this is hit
});
hub.Closed(hub, e => null);
}
public void SomethingToDoWhenClosed(object sender, Func<Exception, Task> e)
{
}
}
类程序
{
公共委托void ClosedEventHandler(对象发送方,函数e);
public ClosedEventHandler Closed{get;set;}
静态void Main(字符串[]参数)
{
程序中心=新程序();
hub.Closed=hub.something到dowhenclosed;
可观察
.FromEventPattern(
h=>hub.Closed+=h,
h=>hub.Closed-=h)
.订阅(x=>
{
//这被击中了
});
hub.Closed(hub,e=>null);
}
public void something todowhenclosed(对象发送方,函数e)
{
}
}
像这样的东西能奏效吗
class Program
{
public event Func<Exception, Task> Closed;
static void Main(string[] args)
{
Program p = new Program();
IObservable<Unit> closedObservable = Observable.Create<Unit>(
observer =>
{
Func<Exception, Task> handler = ex =>
{
observer.OnNext(Unit.Default);
return Task.CompletedTask;
};
p.Closed += handler;
return () => p.Closed -= handler;
});
}
}
类程序
{
公共活动关闭;
静态void Main(字符串[]参数)
{
程序p=新程序();
IObservable closedObservable=可观察。创建(
观察员=>
{
Func handler=ex=>
{
observer.OnNext(默认单位);
返回Task.CompletedTask;
};
p、 闭合+=处理器;
return()=>p.Closed-=handler;
});
}
}
Observable.Create()
对于此类异常情况是一种有用的后备方法
顺便说一句,有一个带有非void返回委托的事件是非常奇怪的,因为引发事件的代码只能看到最后一个要运行的处理程序的值——除非它以某种非标准方式引发事件。但是,既然它是库代码,那就不用你管了 您需要转换重载。每次我查这个东西的时候我都会快门:
IObservable<TEventArgs> Observable.FromEvent<TDelegate, TEventArgs>(
Func<Action<TEventArgs>, TDelegate> conversion,
Action<TDelegate> addHandler,
Action<TDelegate> removeHandler>
)
public委托void ClosedEventHandler(对象发送方,函数)代码>这不会编译错误,消息格式不正确。我已经编辑了它,现在代码显示为OK。我要试试。使用不起作用的链接,返回的主要位置在哪里。对不起,我忘了返回任务,但添加了一个返回任务。例如,完成不会更改任何内容。它不会编译。您还可以等待Observable.FirstAsync。它不会编译,上面显示的代码在VS2017上为我运行,并且能够调试到订阅中。我认为,一旦你添加了额外的异步代码,这是很奇怪的。你能举一个例子,用传统的事件处理代码来使用你的事件吗?这将使它更容易被观察到。谢谢@Enigmativity。我正在使用来自第三方库(SignalR Core)的已关闭事件。事件定义如下:我正在尝试的代码在此repo中:。请随意克隆它。这真的很简单。同时运行服务器和客户端,您将得到异常。@Enigmativity我刚刚添加了带有经典事件处理的代码。我希望这足够了。这让我头疼:)非常感谢!也许这是可行的,但我宁愿使用Observable.FromEvent
或Observable.FromEventPattern
来实现这一点。我怀疑Create
方法在这里是否合理。我希望你能理解。我知道你是从哪里来的,但我怀疑代理是Func
而不是Action
这一事实是非常不寻常的,Rx根本不允许这样做。传统上,它会被认为是“坏的”,尽管我相信信号机开发者对此有很好的理由;-)哦,乍一看,这看起来是个糟糕的设计决定?另外,如果我很了解您的话,问题在于代理的签名是Func
,而不是操作,对吗?没错。我快速查看了您引用的信号器代码,看起来他们似乎在等待返回的任务执行错误日志记录,但是,如果我理解正确,他们将只对其中一个事件处理程序执行此操作。来源:当委托调用的方法的签名包含返回值时,委托将返回调用列表中最后一个元素的返回值
class Program
{
static async Task Main(string[] args)
{
Program.Closed += Program.HubOnClosed;
Observable.FromEvent<Func<Exception, Task>, Exception>(
a => e => {a(e); return Task.CompletedTask; },
h => Program.Closed += h,
h => Program.Closed -= h
)
.Subscribe(e =>
{
Console.WriteLine("Rx: The connection to the hub has been closed");
});
Program.Closed.Invoke(null);
Program.Closed.Invoke(null);
}
private static Task HubOnClosed(Exception arg)
{
Console.WriteLine("The connection to the hub has been closed");
return Task.CompletedTask;
}
public static event Func<Exception, Task> Closed;
}