聪明的方式来获得类型推断?

时间:2016-04-21 06:51:48

标签: c# generics inferred-type

是否有一种聪明的方法可以在“开始”功能中使用类型推断,而无需在Pipe类上定义泛型类型?

使用start会看起来像这样:

Pipe.Start<ToUpper, string, string>(...

我希望它是

Pipe.Start(...

使用用例的完整代码如下所示:

using System;
using System.Threading.Tasks;

namespace Code
{
    public class Pipe
    {
    private Func<object, Task> next;

    public static Section<TOut> Start<TStep, TIn, TOut>(Func<TStep> func, Func<TStep, TIn, TOut> runFunc)
    {
        var pipeline = new Pipe();
        var nextPipe = new Section<TIn>(pipeline);

        pipeline.next = o => nextPipe.Run((TIn)o);

        return nextPipe.Then(func, runFunc);
    }

    public async Task Run<TIn>(TIn start)
    {
        await next(start);
    }

    public class Section<TIn>
    {
        public Pipe Pipe { get; }

        private Func<TIn, Task> next;

        internal Section(Pipe pipe)
        {
            Pipe = pipe;
        }

        public async Task Run(Task<TIn> start)
        {
            if (next != null) await next(await start);
        }

        public async Task Run(TIn start)
        {
            if (next != null) await next(start);
        }

        public Section<TOut> Then<TStep, TOut>(Func<TStep> func, Func<TStep, TIn, TOut> filter)
        {
            var pipeLineStep = new Section<TOut>(Pipe);
            next = @in => pipeLineStep.Run(Task.FromResult(filter(func(), @in)));
            return pipeLineStep;
        }

        public Section<TOut> Then<TStep, TOut>(Func<TStep> func, Func<TStep, TIn, Task<TOut>> runFunc)
        {
            var pipeLineStep = new Section<TOut>(Pipe);
            next = @in => pipeLineStep.Run(runFunc(func(), @in));
            return pipeLineStep;
        }
    }
}
}

测试

using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Code;
using Xunit;

namespace Test
{
public class PipeTets
{
    [Fact]
    public async void FactMethodName()
    {
        var toUpper = new ToUpper();
        var toReverse = new ToReverse();
        var toLower = new ToLower();
        var toLength = new ToLength();
        var toDouble = new ToDouble();

        await Pipe.Start<ToUpper, string, string>(() => toUpper, (upper, s) => upper.Run(s))
                  .Then(() => toReverse, (reverse, s) => reverse.Run(s))
                  .Then(() => toLower, (lower, s) => lower.Run(s))
                  .Then(() => toLength, (length, s) => length.Run(s))
                  .Then(() => toDouble, (@double, i) => @double.Run(i))
                  .Pipe
                  .Run("lower");


        toUpper.Upper.Should().Be("LOWER");
        toReverse.Reverse.Should().Be("REWOL");
        toLower.Lower.Should().Be("rewol");
        toLength.Length.Should().Be(5);
        toDouble.Double.Should().Be(10);
    }
}

public class ToReverse
{
    public string Reverse;

    public string Run(string text)
    {
        Reverse = new string(text.Reverse().ToArray());
        return Reverse;
    }
}

public class ToUpper
{
    public string Upper;

    public string Run(string text)
    {
        Upper = text.ToUpper();
        return Upper;
    }
}

public class ToLower
{
    public string Lower;

    public Task<string> Run(string text)
    {
        Lower = text.ToLower();
        return Task.FromResult(Lower);
    }
}

public class ToLength
{
    public int Length;

    public Task<int> Run(string text)
    {
        Length = text.Length;
        return Task.FromResult(Length);
    }
}

public class ToDouble
{
    public int Double;

    public Task<int> Run(int text)
    {
        Double = text * 2;
        return Task.FromResult(Double);
    }
}
}

1 个答案:

答案 0 :(得分:0)

只需明确定义参数类型:

await Pipe.Start(() => toUpper, (ToUpper upper, string s) => upper.Run(s))