Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.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
C# 如何链接变革性主题<;T、 U>;不使用内部主题<;T、 U>;_C#_System.reactive - Fatal编程技术网

C# 如何链接变革性主题<;T、 U>;不使用内部主题<;T、 U>;

C# 如何链接变革性主题<;T、 U>;不使用内部主题<;T、 U>;,c#,system.reactive,C#,System.reactive,我们有一系列的项目,我们正在处理与反应。处理的一部分是一个可配置的管道,它转换项目(在一个简单的情况下是T->U,例如int->char)。例如,我们的天真实现如下所示 // simple base class, implements IObserver and IObservable which is // equivalent to ISubject<T,U> public abstract class ObservableTask<T, U> : IObserver

我们有一系列的项目,我们正在处理与反应。处理的一部分是一个可配置的管道,它转换项目(在一个简单的情况下是T->U,例如int->char)。例如,我们的天真实现如下所示

// simple base class, implements IObserver and IObservable which is
// equivalent to ISubject<T,U>
public abstract class ObservableTask<T, U> : IObserver<T>, IObservable<U>
{
    // NOTE: stateful, blech
    private readonly Subject<U> observable = new Subject<U>();

    public void OnCompleted() { }
    public void OnError(Exception error) { }
    public void OnNext(T value) { observable.OnNext(Process(value)); }
    public IDisposable Subscribe(IObserver<U> observer) 
    {
        return observable.Subscribe(observer);
    }
    public abstract U Process(T value);
}

// trivial implementation of a transform task, transforms an
// input of type int into an output of type char
public class TransformTask : ObservableTask<int, char>
{
    public override char Process(int value)
    {
        Console.WriteLine("Transform '{0}'", value);
        return (char)(value + 64);
    }
}

// trivial report, does not transform but performs IO-bound
// task and passes value to any other subsequent subscribers
public class ReportTask : ObservableTask<char, char>
{
    public override char Process(char value)
    {
        Console.WriteLine("Report '{0}'", value);
        return value;
    }
}

// simple harness that produces desired output/behaviour
public static class ObservableTasks
{
    public static void ChainThings()
    {
        Console.WriteLine("begin observable tasks");

        // NOTE: would use config/reflection to assemble pipe;
        // here we use concrete instances for demonstration only
        TransformTask a = new TransformTask();
        ReportTask b = new ReportTask();

        int[] numbers = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, };
        var s = numbers.ToObservable().Publish();
        a.Subscribe(b);
        s.Subscribe(a);
        s.Connect();
        Console.WriteLine("begin observable tasks");
    }
}
同样,也有一些好处和成本。相比之下,实现起来更简单,但基础设施将更困难(可观察的动态表达式构造)

首先,是否有人能解决类似的问题并分享一些见解


其次,(我对反应式和函数式编程非常陌生)转换和“动作”(即绑定转换任务和观察者报告任务)是绝对不同的,选择应该用于其中一个,订阅(观察者)另一个?

我不确定您是否需要主题

与其局限于映射,不如转换整个可观察对象,这样就可以使用这样的接口

public interface IStep<T, TResult>
{
    public IObservable<TResult> Transform(IObservable<T> source);
}
公共接口IStep
{
公共IObservable转换(IObservable源);
}
一旦存在,您就可以定义几个扩展方法(只是为了方便)来帮助使用该步骤,如下所示

public static class ObservableExtensions
{
    public static IObservable<TResult> Let(this IObservable<T> source, Func<IObservable<T>, IObservable<TResult>> let)
    {
        return let(source);
    }

    public static IObservable<TResult> Let(this IObservable<T> source, IStep<T, TResult> step)
    {
      return source.Let(step.Transform);
    }
}
public class TransformStep : IStep<int, char>
{
    public IObservable<char> Transform(IObservable<int> source)
    {
        return source.Map(IntToChar); 
    }

    public char IntToChar(int value)
    {
        return (char)(value + 64);
    }
}

public class ReportStep : IStep<char, char>
{
    private readonly Logger logger;

    public ReporterStep(Logger logger)
    {
      this.logger = logger;
    }

    public IObservable<char> Transform(IObservable<char> source)
    {
        return source.Do(Report);
    }

    public void Report(char value)
    {
        logger.Log("Report '{0}'", value);
    }
}
公共静态类ObservableExtensions
{
公共静态IObservable Let(此IObservable源,Func Let)
{
退租(来源);
}
公共静态IObservable Let(此IObservable源,IStep步骤)
{
返回source.Let(step.Transform);
}
}
然后你可以这样定义你的步骤

public static class ObservableExtensions
{
    public static IObservable<TResult> Let(this IObservable<T> source, Func<IObservable<T>, IObservable<TResult>> let)
    {
        return let(source);
    }

    public static IObservable<TResult> Let(this IObservable<T> source, IStep<T, TResult> step)
    {
      return source.Let(step.Transform);
    }
}
public class TransformStep : IStep<int, char>
{
    public IObservable<char> Transform(IObservable<int> source)
    {
        return source.Map(IntToChar); 
    }

    public char IntToChar(int value)
    {
        return (char)(value + 64);
    }
}

public class ReportStep : IStep<char, char>
{
    private readonly Logger logger;

    public ReporterStep(Logger logger)
    {
      this.logger = logger;
    }

    public IObservable<char> Transform(IObservable<char> source)
    {
        return source.Do(Report);
    }

    public void Report(char value)
    {
        logger.Log("Report '{0}'", value);
    }
}
公共类转换步骤:IStep
{
公共IObservable转换(IObservable源)
{
返回source.Map(IntToChar);
}
公共字符IntToChar(int值)
{
返回(字符)(值+64);
}
}
公共类ReportStep:IStep
{
专用只读记录器;
公共报表步骤(记录器)
{
this.logger=记录器;
}
公共IObservable转换(IObservable源)
{
返回源.Do(报告);
}
公共作废报告(字符值)
{
Log(“报告{0}',值);
}
}
并以或多或少一致的方式使用它们

Observable.Return<int>(10)
  .Let(new TransformStep())
  .Let(new ReportStep(logger))
  .Subscribe();
可观察返回(10)
.Let(新的TransformStep())
.Let(新报告步骤(记录器))
.Subscribe();
这样,与每个步骤相关联的所有逻辑都可以是该步骤的内部逻辑,您只需对其进行序列化/反序列化,然后将它们重新链接在一起