可观察事件

时间:2015-07-27 19:39:31

标签: c# events system.reactive

我有这段代码,原始代码here,我需要修改以在字符串列表中插入输出字符串。

我是怎么做到的?

    private static List<string> list_of_proc = new List<string>();

    static void Run<T>(Func<IObservable<T>> f, Action a)
    {
        Action<string> messageTarget = (x) => list_of_proc.Add(x);
        using (f().Subscribe(t => Console.WriteLine(t), p => messageTarget(p)))
        {
            Console.ReadLine();
            Console.WriteLine();
        }
    }

我的操作messageTarget无法编译。

输出错误:

1>Program.cs(20,34,20,59): error CS1660: Cannot convert lambda expression to type 'System.IObserver' because it is not a delegate type
1>Program.cs(20,61,20,82): error CS1593: Delegate 'System.Action' does not take 1 arguments
1>Program.cs(20,61,20,82): error CS1660: Cannot convert lambda expression to type 'System.Threading.CancellationToken' because it is not a delegate type
1>Program.cs(20,66,20,82): error CS1594: Delegate 'System.Action' has some invalid arguments
1>Program.cs(20,80,20,81): error CS1503: Argument 1: cannot convert from 'System.Exception' to 'string'

此代码编译正常,没有错误:

        static void Run<T>(Func<IObservable<T>> f, Action a)
    {
        Action<string> messageTarget = (x) => list_of_proc.Add(x);
        using (f().Subscribe(t => Console.WriteLine(t)/*, p => messageTarget(p)*/))
        {
            Console.ReadLine();
            Console.WriteLine();
        }
    }

订阅具有此表单(System.Reactive.Core.dll,v2.2.5.0):

public static IDisposable Subscribe(this IObservable source, Action onNext);

这个正确的代码:

    static void Run<T>(Func<IObservable<T>> f, Action a)
    {
        Action<string> messageTarget = (x) => list_of_proc.Add(x);
        using (f().Subscribe( t => messageTarget(t.ToString())))
        {
            Console.ReadLine();
            Console.WriteLine();
        }
    }

3 个答案:

答案 0 :(得分:2)

.Subscribe(...)有许多IObservable<T>个扩展方法。编译器将尝试找到最合适的重载。在您的情况下,它按此顺序尝试这些重载:

IDisposable Subscribe<T>(this IObservable<T> source)
IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action onCompleted)
void Subscribe<T>(this IObservable<T> source, Action<T> onNext, CancellationToken token)
IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError)

然而,您的电话是这样的:

.Subscribe(this IObservable<T> source, Action<T> onNext, Action<string> ???)

无匹配,但正试图为您提供有用的提示:

Cannot convert lambda expression to type 'System.IObserver<T>' because it is not a delegate type
Delegate 'System.Action' does not take 1 arguments
Cannot convert lambda expression to type 'System.Threading.CancellationToken' because it is not a delegate type
Delegate 'System.Action<string>' has some invalid arguments

每个人都有效地尝试匹配上述重载之一。

您的代码中不清楚的是运行代码时T的实际类型。为Console.WriteLine(t)类型t调用T意味着您可能强制t.ToString()输出结果 - 这并不会产生有意义的结果。

然后使用Action<T>来跟进Action<string>也没有意义,因为string不是Exception而且那里有.Subscribe(...),而{&#39}没有明确Action<string>的{​​{1}}超载。

我认为你需要的是这样的:

static IObservable<IList<string>> Run<T>(Func<IObservable<T>> f)
{
    return Observable
        .Defer(f)
        .Select(t => t.ToString())
        .ToArray()
        .Select(ss => ss.ToList());
}

或者,或许,这个:

static IObservable<IList<string>> Run<T>(Func<IObservable<T>> f, Func<T, string> toString)
{
    return Observable
        .Defer(f)
        .Select(t => toString(t))
        .ToArray()
        .Select(ss => ss.ToList());
}

然后你可以这样称呼:

Run<int>(() => Observable.Range(0, 3), n => n.ToString())
    .Subscribe(results => /* handle list of results */);

答案 1 :(得分:1)

您正在使用IObserver作为该函数的第一个参数,但实际上您给它一个委托,并且编译器告诉您它不是委托。 就这么简单。

答案 2 :(得分:0)

您的Subscribe方法是扩展方法this参数隐式地是您调用该方法的对象。这意味着您只应将Action委托作为唯一参数传递。

f().Subscribe(() => Console.WriteLine("Hello"))