2016-04-21 10 views
2

Gibt es eine clevere Möglichkeit, Typ-Inferenz-Arbeiten in der "Start" -Funktion zu erhalten, ohne einen generischen Typ für die Pipe-Klasse zu definieren?Cleverer Weg, um Typrückschlüsse zu erhalten?

Anfang Verwendung wird wie folgt aussehen:

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

Ich mag wäre es

Pipe.Start(... 

Voll Code mit usecase sind unten gezeigt werden:

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; 
     } 
    } 
} 
} 

-Test

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); 
    } 
} 
} 
+0

Wäre das nicht ein nützlicher API sein, wenn Ihre Pipeline eine generische Sammlung akzeptiert? Das würde wahrscheinlich auch das Typ-Inferenz-Problem lösen. –

+0

Eine generische Sammlung von Aktionen? Das würde nicht erlauben, dass TIn und TOut für verschiedene Aktionen unterschiedlich sind, oder? – Lejdholt

Antwort

0

definieren Sie die Parameter-Typen explizit:

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

Das funktioniert. Ich nehme es. – Lejdholt

Verwandte Themen