public void VisitLambda() { // Arrange // fingerprints as [ LAMBDA:Func<string, int>, CONST:int, PARAM(0):string ] Expression expr = (Expression <Func <string, int> >)(x => 42); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Equal(new object[] { 42 }, capturedConstants.ToArray()); AssertChainEquals( fingerprint, new LambdaExpressionFingerprint(ExpressionType.Lambda, typeof(Func <string, int>)), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(int)), new ParameterExpressionFingerprint( ExpressionType.Parameter, typeof(string), 0 /* parameterIndex */ ) ); }
public void VisitConditional() { // Arrange // fingerprints as [ CONDITIONAL:int, CONST:bool, CONST:int, CONST:int ] Expression expr = Expression.Condition( Expression.Constant(true), Expression.Constant(42), Expression.Constant(84) ); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Equal(new object[] { true, 42, 84 }, capturedConstants.ToArray()); AssertChainEquals( fingerprint, new ConditionalExpressionFingerprint(ExpressionType.Conditional, typeof(int)), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(bool)), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(int)), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(int)) ); }
public void VisitIndex() { // Arrange // fingerprints as [ INDEX:object, PARAM(0):object[], CONST:int ] Expression expr = Expression.MakeIndex( Expression.Parameter(typeof(object[])), null /* indexer */ , new Expression[] { Expression.Constant(42) } ); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Equal(new object[] { 42 }, capturedConstants.ToArray()); AssertChainEquals( fingerprint, new IndexExpressionFingerprint( ExpressionType.Index, typeof(object), null /* indexer */ ), new ParameterExpressionFingerprint( ExpressionType.Parameter, typeof(object[]), 0 /* parameterIndex */ ), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(int)) ); }
public void VisitUnary() { // Arrange // fingerprints as [ OP_NOT:int, PARAM:int ] Expression expr = Expression.Not(Expression.Parameter(typeof(int))); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Empty(capturedConstants); AssertChainEquals( fingerprint, new UnaryExpressionFingerprint( ExpressionType.Not, typeof(int), null /* method */ ), new ParameterExpressionFingerprint( ExpressionType.Parameter, typeof(int), 0 /* parameterIndex */ ) ); }
internal static void AssertChainEquals(ExpressionFingerprintChain fingerprintChain, params ExpressionFingerprint[] expectedElements) { ExpressionFingerprintChain newChain = new ExpressionFingerprintChain(); newChain.Elements.AddRange(expectedElements); Assert.Equal(fingerprintChain, newChain); }
public void VisitParameter() { // Arrange // fingerprints as [ LAMBDA:Func<int, int, int>, OP_ADD:int, OP_ADD:int, OP_ADD:int, PARAM(0):int, PARAM(0):int, PARAM(1):int, PARAM(0):int, PARAM(1):int, PARAM(0):int ] // (note that the parameters are out of order since 'y' is used first, but this is ok due // to preservation of alpha equivalence within the VisitParameter method.) Expression expr = (Expression <Func <int, int, int> >)((x, y) => y + y + x + y); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Empty(capturedConstants); AssertChainEquals(fingerprint, new LambdaExpressionFingerprint(ExpressionType.Lambda, typeof(Func <int, int, int>)), new BinaryExpressionFingerprint(ExpressionType.Add, typeof(int), null /* method */), new BinaryExpressionFingerprint(ExpressionType.Add, typeof(int), null /* method */), new BinaryExpressionFingerprint(ExpressionType.Add, typeof(int), null /* method */), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(int), 0 /* parameterIndex */), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(int), 0 /* parameterIndex */), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(int), 1 /* parameterIndex */), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(int), 0 /* parameterIndex */), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(int), 1 /* parameterIndex */), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(int), 0 /* parameterIndex */)); }
public void VisitBinary() { // Arrange // fingerprints as [ OP_GREATERTHAN:bool, CONST:int, CONST:int ] Expression expr = Expression.MakeBinary( ExpressionType.GreaterThan, Expression.Constant(42), Expression.Constant(84) ); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Equal(new object[] { 42, 84 }, capturedConstants.ToArray()); AssertChainEquals( fingerprint, new BinaryExpressionFingerprint( ExpressionType.GreaterThan, typeof(bool), null /* method */ ), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(int)), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(int)) ); }
public void VisitMethodCall() { // Arrange // fingerprints as [ CALL(GC.KeepAlive):void, NULL, PARAM(0):object ] Expression expr = Expression.Call( typeof(GC).GetMethod("KeepAlive"), Expression.Parameter(typeof(object)) ); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Empty(capturedConstants); AssertChainEquals( fingerprint, new MethodCallExpressionFingerprint( ExpressionType.Call, typeof(void), typeof(GC).GetMethod("KeepAlive") ), _nullFingerprint, new ParameterExpressionFingerprint( ExpressionType.Parameter, typeof(object), 0 /* parameterIndex */ ) ); }
public void Hoist() { // Arrange Expression <Func <string, int> > expr = s => 2 * s.Length + 1; // Act Expression <Hoisted <string, int> > hoisted = HoistingExpressionVisitor <string, int> .Hoist(expr); // Assert // new expression should be (s, capturedConstants) => (int)(capturedConstants[0]) * s.Length + (int)(capturedConstants[1]) // with fingerprint [ LAMBDA:Hoisted<string, int>, OP_ADD:int, OP_MULTIPLY:int, OP_CAST:int, INDEX(List<object>.get_Item):object, PARAM(0):List<object>, CONST:int, MEMBER(String.Length):int, PARAM(1):string, OP_CAST:int, INDEX(List<object>.get_Item):object, PARAM(0):List<object>, CONST:int, PARAM(1):string, PARAM(0):List<object> ] List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(hoisted, out capturedConstants); Assert.Equal(new object[] { 0, 1 }, capturedConstants.ToArray()); // these are constants from the hoisted expression (array indexes), not the original expression FingerprintingExpressionVisitorTest.AssertChainEquals( fingerprint, new LambdaExpressionFingerprint(ExpressionType.Lambda, typeof(Hoisted <string, int>)), new BinaryExpressionFingerprint(ExpressionType.Add, typeof(int), null /* method */), new BinaryExpressionFingerprint(ExpressionType.Multiply, typeof(int), null /* method */), new UnaryExpressionFingerprint(ExpressionType.Convert, typeof(int), null /* method */), new IndexExpressionFingerprint(ExpressionType.Index, typeof(object), typeof(List <object>).GetProperty("Item")), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(List <object>), 0 /* parameterIndex */), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(int)), new MemberExpressionFingerprint(ExpressionType.MemberAccess, typeof(int), typeof(string).GetProperty("Length")), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(string), 1 /* parameterIndex */), new UnaryExpressionFingerprint(ExpressionType.Convert, typeof(int), null /* method */), new IndexExpressionFingerprint(ExpressionType.Index, typeof(object), typeof(List <object>).GetProperty("Item")), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(List <object>), 0 /* parameterIndex */), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(int)), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(string), 1 /* parameterIndex */), new ParameterExpressionFingerprint(ExpressionType.Parameter, typeof(List <object>), 0 /* parameterIndex */)); }
public void Visit_Null() { // Arrange // fingerprints as [ NULL ] Expression expr = null; // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Empty(capturedConstants); AssertChainEquals(fingerprint, _nullFingerprint); }
public void VisitDefault() { // Arrange // fingerprints as [ DEFAULT:int ] Expression expr = Expression.Default(typeof(int)); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Empty(capturedConstants); AssertChainEquals(fingerprint, new DefaultExpressionFingerprint(ExpressionType.Default, typeof(int))); }
public void VisitConstant() { // Arrange // fingerprints as [ CONST:int ] Expression expr = Expression.Constant(42); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Equal(new object[] { 42 }, capturedConstants.ToArray()); AssertChainEquals(fingerprint, new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(int))); }
public void Visit_Unknown() { // Arrange // if we fingerprinted ctors, would fingerprint as [ NEW(StringBuilder(int)):StringBuilder, PARAM(0):int ] // but since we don't fingerprint ctors, should just return null (signaling failure) Expression expr = (Expression <Func <int, StringBuilder> >)(capacity => new StringBuilder(capacity)); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Null(fingerprint); // Can't fingerprint ctor Assert.Null(capturedConstants); // Can't fingerprint ctor }
public void VisitMember() { // Arrange // fingerprints as [ MEMBER(String.Empty):string, NULL ] Expression expr = Expression.Field(null, typeof(string), "Empty"); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Empty(capturedConstants); AssertChainEquals(fingerprint, new MemberExpressionFingerprint(ExpressionType.MemberAccess, typeof(string), typeof(string).GetField("Empty")), _nullFingerprint); }
public void VisitTypeBinary() { // Arrange // fingerprints as [ TYPEIS(DateTime):bool, CONST:string ] Expression expr = Expression.TypeIs(Expression.Constant("hello"), typeof(DateTime)); // Act List <object> capturedConstants; ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants); // Assert Assert.Equal(new object[] { "hello" }, capturedConstants.ToArray()); AssertChainEquals(fingerprint, new TypeBinaryExpressionFingerprint(ExpressionType.TypeIs, typeof(bool), typeof(DateTime)), new ConstantExpressionFingerprint(ExpressionType.Constant, typeof(string))); }
private static Func <TIn, TOut> CompileFromFingerprint(Expression <Func <TIn, TOut> > expr) { ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out List <object> capturedConstants); if (fingerprint != null) { var del = _fingerprintedCache.GetOrAdd(fingerprint, _ => { // Fingerprinting succeeded, but there was a cache miss. Rewrite the expression // and add the rewritten expression to the cache. var hoistedExpr = HoistingExpressionVisitor <TIn, TOut> .Hoist(expr); return(hoistedExpr.Compile()); }); return(model => del(model, capturedConstants)); } // couldn't be fingerprinted return(null); }
internal static void AssertChainEquals(ExpressionFingerprintChain fingerprintChain, params ExpressionFingerprint[] expectedElements) { ExpressionFingerprintChain newChain = new ExpressionFingerprintChain(); newChain.Elements.AddRange(expectedElements); Assert.AreEqual(fingerprintChain, newChain); }