|
2 | 2 | using System.Collections.Generic; |
3 | 3 | using System.Diagnostics; |
4 | 4 | using System.Linq; |
| 5 | +using System.Linq.Expressions; |
| 6 | +using System.Reflection; |
5 | 7 | using System.Text; |
6 | 8 | using Elastic.Xunit.XunitPlumbing; |
7 | 9 | using FluentAssertions; |
| 10 | +using Microsoft.FSharp.Core; |
8 | 11 | using Nest; |
9 | 12 | using Tests.Domain; |
10 | 13 | using Xunit.Abstractions; |
@@ -534,5 +537,116 @@ public override string ToString() => |
534 | 537 | $"First hit for {Name} took {FirstHit}ms, Cached hit took {CachedHit}ms ({FirstHit / CachedHit}x faster)."; |
535 | 538 | } |
536 | 539 | } |
| 540 | + |
| 541 | + public class ExpressionExtensions |
| 542 | + { |
| 543 | + private class Doc |
| 544 | + { |
| 545 | + public string Prop { get; set; } |
| 546 | + } |
| 547 | + |
| 548 | + private readonly FieldInfo _propertyNameComparisonField; |
| 549 | + private readonly FieldInfo _propertyNameTypeField; |
| 550 | + private FieldInfo _fieldComparisonField; |
| 551 | + private FieldInfo _fieldTypeField; |
| 552 | + |
| 553 | + public ExpressionExtensions() |
| 554 | + { |
| 555 | + _propertyNameComparisonField = typeof(PropertyName).GetField("_comparisonValue", BindingFlags.Instance | BindingFlags.NonPublic); |
| 556 | + _propertyNameTypeField = typeof(PropertyName).GetField("_type", BindingFlags.Instance | BindingFlags.NonPublic); |
| 557 | + _fieldComparisonField = typeof(Field).GetField("_comparisonValue", BindingFlags.Instance | BindingFlags.NonPublic); |
| 558 | + _fieldTypeField = typeof(Field).GetField("_type", BindingFlags.Instance | BindingFlags.NonPublic); |
| 559 | + } |
| 560 | + |
| 561 | + [U] |
| 562 | + public void CanCacheLambdaExpressionPropertyName() |
| 563 | + { |
| 564 | + Expression<Func<Doc, string>> expression = d => d.Prop; |
| 565 | + |
| 566 | + var property = new PropertyName(expression); |
| 567 | + property.CacheableExpression.Should().BeTrue(); |
| 568 | + |
| 569 | + var value = _propertyNameComparisonField.GetValue(property); |
| 570 | + value.Should().BeOfType<string>().And.Be(nameof(Doc.Prop)); |
| 571 | + _propertyNameTypeField.GetValue(property).Should().Be(typeof(Doc)); |
| 572 | + } |
| 573 | + |
| 574 | + [U] |
| 575 | + public void CanCacheMemberExpressionPropertyName() |
| 576 | + { |
| 577 | + var parameterExpression = Expression.Parameter(typeof(Doc), "x"); |
| 578 | + var expression = Expression.Property(parameterExpression, typeof(Doc).GetProperty(nameof(Doc.Prop))); |
| 579 | + |
| 580 | + var property = new PropertyName(expression); |
| 581 | + property.CacheableExpression.Should().BeTrue(); |
| 582 | + |
| 583 | + var value = _propertyNameComparisonField.GetValue(property); |
| 584 | + value.Should().BeOfType<string>().And.Be(nameof(Doc.Prop)); |
| 585 | + _propertyNameTypeField.GetValue(property).Should().Be(typeof(Doc)); |
| 586 | + } |
| 587 | + |
| 588 | + [U] |
| 589 | + public void CanCacheFSharpFuncMethodCallExpressionPropertyName() |
| 590 | + { |
| 591 | + Expression<Func<Doc, string>> lambdaExpression = d => d.Prop; |
| 592 | + var expression = Expression.Call( |
| 593 | + typeof(FuncConvert), |
| 594 | + "ToFSharpFunc", |
| 595 | + new[] { typeof(Doc), typeof(string) }, |
| 596 | + lambdaExpression); |
| 597 | + |
| 598 | + var property = new PropertyName(expression); |
| 599 | + property.CacheableExpression.Should().BeTrue(); |
| 600 | + |
| 601 | + var value = _propertyNameComparisonField.GetValue(property); |
| 602 | + value.Should().BeOfType<string>().And.Be(nameof(Doc.Prop)); |
| 603 | + _propertyNameTypeField.GetValue(property).Should().Be(typeof(Doc)); |
| 604 | + } |
| 605 | + |
| 606 | + [U] |
| 607 | + public void CanCacheLambdaExpressionField() |
| 608 | + { |
| 609 | + Expression<Func<Doc, string>> expression = d => d.Prop; |
| 610 | + |
| 611 | + var field = new Field(expression); |
| 612 | + field.CachableExpression.Should().BeTrue(); |
| 613 | + |
| 614 | + var value = _fieldComparisonField.GetValue(field); |
| 615 | + value.Should().BeOfType<string>().And.Be(nameof(Doc.Prop)); |
| 616 | + _fieldTypeField.GetValue(field).Should().Be(typeof(Doc)); |
| 617 | + } |
| 618 | + |
| 619 | + [U] |
| 620 | + public void CanCacheMemberExpressionField() |
| 621 | + { |
| 622 | + var parameterExpression = Expression.Parameter(typeof(Doc), "x"); |
| 623 | + var expression = Expression.Property(parameterExpression, typeof(Doc).GetProperty(nameof(Doc.Prop))); |
| 624 | + |
| 625 | + var field = new Field(expression); |
| 626 | + field.CachableExpression.Should().BeTrue(); |
| 627 | + |
| 628 | + var value = _fieldComparisonField.GetValue(field); |
| 629 | + value.Should().BeOfType<string>().And.Be(nameof(Doc.Prop)); |
| 630 | + _fieldTypeField.GetValue(field).Should().Be(typeof(Doc)); |
| 631 | + } |
| 632 | + |
| 633 | + [U] |
| 634 | + public void CanCacheFSharpFuncMethodCallExpressionField() |
| 635 | + { |
| 636 | + Expression<Func<Doc, string>> lambdaExpression = d => d.Prop; |
| 637 | + var expression = Expression.Call( |
| 638 | + typeof(FuncConvert), |
| 639 | + "ToFSharpFunc", |
| 640 | + new[] { typeof(Doc), typeof(string) }, |
| 641 | + lambdaExpression); |
| 642 | + |
| 643 | + var field = new Field(expression); |
| 644 | + field.CachableExpression.Should().BeTrue(); |
| 645 | + |
| 646 | + var value = _fieldComparisonField.GetValue(field); |
| 647 | + value.Should().BeOfType<string>().And.Be(nameof(Doc.Prop)); |
| 648 | + _fieldTypeField.GetValue(field).Should().Be(typeof(Doc)); |
| 649 | + } |
| 650 | + } |
537 | 651 | } |
538 | 652 | } |
0 commit comments