使用流畅的语法自动将“ TInput”设置为等于“ TOutput”

问题描述

我正在使用流利的语法构建个人自动化框架。这是管道示例

 var pipeline = Core.Runner.CreatePipeline()
                .BeginMany(Sources.Csv(@"..."))
                .ThenTransform<dynamic,string[]>(record=> record.id.Split(":"))
                .ThenTransform<string[],(string,string)>(record => (record[0],record[1]))
                .ThenTransform<(string,string),dynamic>(new {...})

我想知道有什么方法可以提高可用性,并自动为链中的下一个TInput设置TOutput等于ThenTransform<TInput,TOutput>并在构建时验证类型吗?

期望的结果

 var pipeline = Core.Runner.CreatePipeline()
                .BeginMany(Sources.Csv(@"..."))
                .ThenTransform<string[]>(record=> record.id.Split(":")) // TInput is dynamic,TOutput is string[]
                .ThenTransform<(string,record[1])) // TInput is string[],TOuput is (string,string)
                .ThenTransform<dynamic>(new {...}) // etc

由于lambda知道返回类型,因此可能会有更好的结果

 var pipeline = Core.Runner.CreatePipeline()
                .BeginMany(Sources.Csv(@"..."))
                .ThenTransform(record=> record.id.Split(":")) // TInput is dynamic,TOutput is string[]
                .ThenTransform(record => (record[0],string)
                .ThenTransform(new {...}) // etc

解决方法

您尚未在此处指定如何存储状态,但是对于泛型,您可以执行以下操作:

using System;

namespace ConsoleApp16
{
    class Program
    {
        static void Main(string[] args)
        {
            var pipeline = Core.Runner.CreatePipeline<dynamic>()
                .BeginMany(Sources.Csv(@"..."))
                // Type cannot be inferred from dynamic
                .ThenTransform<string[]>(record => record.id.Split(":")) 
                .ThenTransform(record => (record[0],record[1]))
                .ThenTransform(s => s.Item1);
        }
    }

    internal class Sources
    {
        public static object Csv(string s)
        {
            return new object();
        }
    }

    internal class Core
    {
        public class Runner
        {
            public static Pipeline<TInput> CreatePipeline<TInput>()
            {
                return new Pipeline<TInput>(new PipelineState());
            }
        }
    }

    internal class PipelineState
    {
        public bool MyState { get; set; }
    }

    internal class Pipeline<TInput>
    {
        private readonly PipelineState _pipelineState;

        public Pipeline(PipelineState pipelineState)
        {
            _pipelineState = pipelineState;
        }

        public Pipeline<TInput> BeginMany(object csv)
        {
            // Update state
            return this;
        }

        public Pipeline<TOutput> ThenTransform<TOutput>(Func<TInput,TOutput> func)
        {
            // Update state
            return new Pipeline<TOutput>(_pipelineState);
        }
    }
}

您可以通过使用不同方法返回的不同PipelineBuilder类来对此进行改进。例如,BeginMany可能返回一个具有ThenTransform方法的类,以便强制执行该顺序:

using System;

namespace ConsoleApp16
{
    class Program
    {
        static void Main(string[] args)
        {
            var pipeline = Core.Runner.CreatePipeline()
                .BeginMany(Sources.Csv(@"..."))
                // Type cannot be inferred from dynamic
                .ThenTransform<string[]>(record => record.id.Split(":"))
                .ThenTransform(record => (record[0],record[1]))
                .ThenTransform(s => s.Item1)
                .Build();
        }
    }

    internal class Sources
    {
        public static Source<dynamic> Csv(string s)
        {
            return new Source<dynamic>();
        }
    }

    internal class Source<T>
    {
    }

    internal class Core
    {
        public class Runner
        {
            public static PipelineBuilder CreatePipeline()
            {
                return new PipelineBuilder(new PipelineState());
            }
        }
    }

    internal class PipelineState
    {
        public bool MyState { get; set; }
    }

    internal class PipelineBuilder
    {
        protected readonly PipelineState State;

        public PipelineBuilder(PipelineState state)
        {
            State = state;
        }

        public PipelineBuilder<TInput> BeginMany<TInput>(Source<TInput> source)
        {
            // Update state
            return new PipelineBuilder<TInput>(State);
        }

        public Pipeline Build()
        {
            // Populate from state
            return new Pipeline();
        }
    }


    internal class PipelineBuilder<TInput> : PipelineBuilder
    {
        public PipelineBuilder(PipelineState pipelineState) : base(pipelineState)
        {
        }

        public PipelineBuilder<TOutput> ThenTransform<TOutput>(Func<TInput,TOutput> func)
        {
            // Update state
            return new PipelineBuilder<TOutput>(State);
        }
    }

    internal class Pipeline
    {
    }
}

值得研究构建器模式,当与接口和扩展方法结合使用时,它可能会非常强大。一个很好的例子是Microsoft.Extensions.Configuration https://github.com/dotnet/extensions/tree/release/3.1/src/Configuration

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...