2010年9月25日星期六

神一般的一段代码~

收到Elevate(http://elevate.codeplex.com)项目里Pattern Match的启发,对它的实现进行了一些改进,于是写出了这样一段神一般的代码来~
不知道是不是有人能读懂段代码~
代码里把C#的Generic, Extension Method, Lambda Expression, Explicit Implemented Interface等Feature用到了极致~特别是Generic!
太神奇了~哈哈~

为了好理解,先放上一些Elevate 里关于 Pattern Match 的 Sample Code:
/// <summary> /// Pattern matching is used in functional languages. It can be thought of as a "switch statement on steriods"./// Here's an example of very basic pattern matching using Elevate. /// </summary>[Fact]public void PatternMatchingWithFunctions() {        //given a value        var value = "alpha";         var result = value.Match() //we can start a pattern match like this                 .With(string.IsNullOrEmpty, stringValue => "empty") //causes the pattern match to return "empty" if value is null or empty                 .With(stringValue => value.Contains("a"), stringValue => "contains a!") //match any string containing "a"                 .EndMatch();         Assert.Equal("contains a!", result); } [Fact]public void PatternMatchingWithMatchPatternsAsValues(){        //given a value         var value = "gamma";         //we can equality match against values without having to specify         //a condition function        var result = value.Match()                .With("alpha", stringValue => "1st letter = " + stringValue)                 .With("beta", stringValue => "2nd letter = " + stringValue)                 .With("gamma", stringValue => "3rd letter = " + stringValue)                 .EndMatch();         Assert.Equal("3rd letter = gamma", result); } [Fact]public void PatternMatchingWithMatchPatternsAndResultsAsValues(){        //given a value         var value = "gamma";         //we can also match without having to speficy a lambda for either the         //match predicate or the result        var result = value.Match()                .With("alpha", "first letter")                 .With("beta", "second letter")                .With("gamma", "third letter")                 .EndMatch();         Assert.Equal("third letter", result); } [Fact]public void IncompletePatternMatching(){        //given a value         var stringValue = "alpha, beta";         //if we construct a pattern match that does not match the value         Assert.ThrowsDelegateWithReturn incompleteMatch = () =>                                                         stringValue.Match()                                                        .With(value => value == "alpha", value => "Found foo")                                                         .With(value => value == "beta", value => "Found bar")                                                         .EndMatch();         //evaluating it will throw        Assert.Throws<IncompletePatternMatchException>(incompleteMatch); } [Fact]public void PatternMatchingWithElse(){        //given a value         var stringValue = "alpha, beta";         //we can add Else to cause the incomplete match from above to have a         //default case        var elseMatch =                stringValue.Match()                .With(value => value == "alpha", value => "Found foo")                 .With(value => value == "beta", value => "Found bar")                 .Else(value => "default!")                .EndMatch();         Assert.Equal("default!", elseMatch); } [Fact]public void PatternMatchingElseWithValues(){        //given a value         var stringValue = "alpha, beta";         //we can specify else as a concrete value without having         //to use the input value        var elseMatch =                stringValue.Match()                .With(value => value == "alpha", value => "Found foo")                 .With(value => value == "beta", value => "Found bar")                 .Else("default!")                .EndMatch();         Assert.Equal("default!", elseMatch); }
Elevate原来的代码仅仅支持用一次,没有办法把这个Pattern给持久化住,然后apply给一系列的值~
这是个比较致命的缺陷,于是,我开始研究它的代码~

Elevate中关于Pattern  Match比较关键的几个类是
/// <summary>/// A class containing extensions methods to enable pattern matching. /// </summary>public static class ObjectExtensionsForPatternMatching {    /// <summary>    /// Begins a pattern match on the specified value     /// </summary>    /// <typeparam name="T">The type of the value being matched.</typeparam>     /// <param name="value">The value to match.</param>     /// <returns>The matching context</returns>     public static PatternMatchContext<T> Match<T>(this T value)     {        return new PatternMatchContext<T>(value);     }}
/// <summary>
/// A partially complete pattern match with only the input type specified./// </summary> /// <typeparam name="T">The type returned by this pattern match</typeparam> public class PatternMatchContext<T> {    internal readonly T value;     internal PatternMatchContext(T value)    {        this.value = value;     }     /// <summary>    /// Specifies the first condition to match against. Also defines the type of the result value.     /// </summary>    /// <typeparam name="TResult">The type of the result.</typeparam>     /// <param name="condition">The condition to match against.</param>     /// <param name="result">The result to return if this condition matches.</param>     /// <returns>The pattern match with the selector defined</returns>     public PatternMatch<T, TResult> With<TResult>(         Func<T, bool> condition,        Func<T, TResult> result)     {        if (condition == null)            throw new ArgumentNullException("condition", "condition is null.");         if (result == null)            throw new ArgumentNullException("result", "result is null.");         var match = new PatternMatch<T, TResult>(value);         return match.With(condition, result);    }}
/// <summary> /// A pattern matching block with the return value and the/// the type to match on specified. /// </summary>/// <typeparam name="T">The type of the value being matched.</typeparam> /// <typeparam name="TResult">The type of the result.</typeparam> public class PatternMatch<T, TResult> {    private readonly T value;    private readonly List<Tuple<Func<T, bool>, Func<T, TResult>>> cases          = new List<Tuple<Func<T, bool>, Func<T, TResult>>>();     private Func<T, TResult> elseFunc;     internal PatternMatch(T value)     {        this.value = value;    }     /// <summary>     /// Specifies a condition to match against, and the value to return    /// </summary>     /// <param name="matchCondition">The condition to match with.</param>     /// <param name="matchResult">The result to return if the condition matches.</param>     /// <returns>The current PatternMatch</returns>     public PatternMatch<T, TResult> With(Func<T, bool> matchCondition, Func<T, TResult> matchResult)     {        if (matchCondition == null)            throw new ArgumentNullException("matchCondition", "matchCondition is null.");         if (matchResult == null)            throw new ArgumentNullException("matchResult", "matchResult is null.");         cases.Add(Tuple.Create(matchCondition, matchResult));        return this;     }     /// <summary>    /// Specifies a default result if all conditions fail to match.     /// </summary>    /// <param name="result">The result.</param>     /// <returns>The current PatternMatch</returns>     public PatternMatch<T, TResult> Else(Func<T, TResult> result)     {        if (elseFunc != null)            throw new InvalidOperationException("Cannot have multiple else cases");         elseFunc = result;        return this;    }     /// <summary>     /// Evaluates this pattern match, returning the result of the condition that matches.    /// </summary>     /// <returns>the match resulg</returns>     /// <remarks>If this does not contain a match, this method    /// throws an IncompleteMatchException</remarks>     public TResult EndMatch()    {        if (elseFunc != null)             cases.Add(                Tuple.Create<Func<T, bool>, Func<T, TResult>>(x => true, elseFunc));         foreach (var item in cases)            if (item.First(value))                 return item.Second(value);         throw new IncompleteMatchException("Incomplete pattern match");     }}
由代码可知,Elevate的形成的Function Call Chain中的Context的切换完全是通过返回不同类型的class实现的~在一次一用的环境里,没有问题,但是如果在需要持久化的Case里就会有一些问题~
由于一次一用的实现和持久化的实现的代码几乎没有任何区别~但是Context的切换则会有非常大的不同,如何能够在重用实现的情况下还产生不同的Context(VS的IntelliSence会检测到这种区别,同时在没有强制类型转换的情况下,用户无法调用本不应该调用的Method,例如对一个持久化版的PatternMatch去调用EndMatch()方法,相应的,用户应该调用Apply方法)。
最后我想到了可以利用Interface去标识上下文,而利用同一个class去实现所有的interface,这样,context在切换,但是数据没有复制,调用永远都是一个class。
然而这个时候有存在问题了,由于需要实现ExtensionMethod,为了尽可能的复用代码,我比如让一些方法共集中到一个Interface里,但是同一个方法的调用,返回的Context Interface在一次一用和持久化的场景里,又应该有所不同,于是问题就彻底复杂话了~于是Generic的终极使用方法出现了————Generic的迭代。
public interface IWithContext<T, TResult, TSelf>     where TSelf : IWithContext<T, TResult, TSelf>{    TSelf With(Func<T, bool> condition, Func<T, TResult> result); }
注意 TSelf 的限定~华丽丽的限定!还有With方法的返回类型!哈哈~
这里是完整的代码:
好复杂的继承关系!
public class PatternMatch<T, TResult> :         IInstantMatchContext<T, TResult>,        IWithContext<T, TResult, IInstantMatchContext<T, TResult>>,         IElseContext<T, TResult, IEndMatchContext<TResult>>,         IEndMatchContext<TResult>,        ICompileMatchContext<T, TResult>,         IWithContext<T, TResult, ICompileMatchContext<T, TResult>>,         IElseContext<T, TResult, IAppliableCompilableContext<T, TResult>>,         IAppliableCompilableContext<T, TResult>,        ICompilableContext<T, TResult>,         IApplyContext<T, TResult>{    #region Constructors     internal PatternMatch()    {        HasValue = false;        Cases = new List<MatchCase>();         ElseCase = null;    }     internal PatternMatch(T input)        : this()     {        this.Input = input;        HasValue = true;     }     #endregion     #region Instant Mode Status Fields     private T Input;    private bool HasValue;     #endregion     #region Common Runtime Status Fields     protected List<MatchCase> Cases;     protected Func<T, TResult> ElseCase;     #endregion     #region Functional Methods     protected PatternMatch<T, TResult> With(Func<T, bool> condition, Func<T, TResult> result)     {        if (condition == null)            throw new ArgumentNullException("condition", "condition is null.");         if (result == null)            throw new ArgumentNullException("result", "result is null.");         Cases.Add(new MatchCase(condition, result));        return this;     }     protected PatternMatch<T, TResult> Else(Func<T, TResult> result)     {        if (result == null)            throw new ArgumentNullException("result", "result is null.");         ElseCase = result;         return this;    }     protected TResult EndMatch()     {        if (!HasValue)            throw new InvalidOperationException();         return Apply(Input);    }     protected IApplyContext<T, TResult> Compile()     {        return this;    }     protected TResult Apply(T input)    {        foreach (var foCase in Cases)         {            if (foCase.Condition(input))                return foCase.Result(input);         }         if (ElseCase != null)            return ElseCase(input);         else            throw new IncompletePatternMatchException();     }     #endregion     #region Nested Entity     protected struct MatchCase     {        public MatchCase(Func<T, bool> condition, Func<T, TResult> result)         {            this.Condition = condition;            this.Result = result;         }        public Func<T, bool> Condition;         public Func<T, TResult> Result;    }     #endregion     #region Contextual Methods     #region Instant Mode     #region IWithContext<T,TResult,IInstantMatchContext<T,TResult>> Members     IInstantMatchContext<T, TResult> IWithContext<T, TResult, IInstantMatchContext<T, TResult>>.With(Func<T, bool> condition, Func<T, TResult> result)     {        return this.With(condition, result);    }     #endregion     #region IElseContext<T,TResult,IEndMatchContext<TResult>> Members     IEndMatchContext<TResult> IElseContext<T, TResult, IEndMatchContext<TResult>>.Else(Func<T, TResult> result)     {        return this.Else(result);    }     #endregion     #region IEndMatchContext<TResult> Members     TResult IEndMatchContext<TResult>.EndMatch()     {        return this.EndMatch();    }     #endregion     #endregion     #region Compile Mode     #region IWithContext<T,TResult,ICompileMatchContext<T,TResult>> Members     ICompileMatchContext<T, TResult> IWithContext<T, TResult, ICompileMatchContext<T, TResult>>.With(Func<T, bool> condition, Func<T, TResult> result)     {        return this.With(condition, result);    }     #endregion     #region IElseContext<T,TResult,IAppliableCompilableContext<T,TResult>> Members     IAppliableCompilableContext<T, TResult> IElseContext<T, TResult, IAppliableCompilableContext<T, TResult>>.Else(Func<T, TResult> result)     {        return this.Else(result);    }     #endregion     #region ICompilableContext<T,TResult> Members     IApplyContext<T, TResult> ICompilableContext<T, TResult>.Compile()     {        return this.Compile();    }     #endregion     #region IApplyContext<T,TResult> Members     TResult IApplyContext<T, TResult>.Apply(T input)     {        return this.Apply(input);    }     #endregion     #endregion     #endregion}
public class InitialWithContext<T> : IWithContext<T>
{    private T input;     internal InitialWithContext(T input)     {         this.input = input;    }     #region IWithContext<T> Members     public IInstantMatchContext<T, TResult> With<TResult>(Func<T, bool> condition, Func<T, TResult> result)     {        return (new PatternMatch<T, TResult>(input) as IInstantMatchContext<T, TResult>).With(condition, result);     }     #endregion}
public static class PatternMatch
{    public static <span

Posted via email from 米良的实验室

没有评论:

发表评论