From 5542f1b5ccbf17de0ce7901f3de404a5bf28f977 Mon Sep 17 00:00:00 2001 From: Marcin Kasperski Date: Mon, 15 Jan 2018 01:46:31 +0100 Subject: [PATCH 1/5] Fixes for ExpressionKeyVisitor to produce unique keys for anonymous types --- src/NHibernate.DomainModel/AnonymousType1.cs | 28 ++++++++++++++++++ .../NHSpecificTest/GH1526/AnonymousType1.cs | 29 +++++++++++++++++++ .../NHSpecificTest/GH1526/Fixture.cs | 23 +++++++++++++++ .../Linq/Visitors/ExpressionKeyVisitor.cs | 2 +- 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/NHibernate.DomainModel/AnonymousType1.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs create mode 100644 src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs diff --git a/src/NHibernate.DomainModel/AnonymousType1.cs b/src/NHibernate.DomainModel/AnonymousType1.cs new file mode 100644 index 00000000000..7a86e60df90 --- /dev/null +++ b/src/NHibernate.DomainModel/AnonymousType1.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; + +// ReSharper disable once CheckNamespace +// Simulates compiler-generated, non-namespaced anonymous type +internal class AnonymousType1 +{ + public T Name { get; set; } +} + +namespace NHibernate.DomainModel +{ + // Produces an Expression that has the above AnonymousType1 embedded in it + public static class AnonymousTypeExpressionProviderFromNHibernateDomainModelAssembly + { + public static Expression GetExpression() + { + Expression>>> exp = () => + Enumerable.Empty() + .Select(c => new AnonymousType1 { Name = c.Name }) + .ToList(); + + return exp; + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs new file mode 100644 index 00000000000..90f0afdf460 --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using NHibernate.DomainModel; + +// ReSharper disable once CheckNamespace +// Simulates a compiler-generated, non-namespaced anonymous type +internal class AnonymousType1 +{ + public T Name { get; set; } +} + +namespace NHibernate.Test.NHSpecificTest.GH1526 +{ + // Produces an Expression that has the above AnonymousType1 embedded in it + public static class AnonymousTypeExpressionProviderFromNHibernateTestAssembly + { + public static Expression GetExpression() + { + Expression>>> exp = () => + Enumerable.Empty() + .Select(c => new AnonymousType1 { Name = c.Name }) + .ToList(); + + return exp; + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs new file mode 100644 index 00000000000..bd4db94744f --- /dev/null +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs @@ -0,0 +1,23 @@ +using System; +using NHibernate.DomainModel; +using NHibernate.Linq.Visitors; +using NUnit.Framework; + +namespace NHibernate.Test.NHSpecificTest.GH1526 +{ + [TestFixture] + public class Fixture + { + [Test] + public void ShouldCreateDifferentKeyForAnonymousTypesFromDifferentAssemblies() + { + var exp1 = AnonymousTypeExpressionProviderFromNHibernateTestAssembly.GetExpression(); + var exp2 = AnonymousTypeExpressionProviderFromNHibernateDomainModelAssembly.GetExpression(); + + var key1 = ExpressionKeyVisitor.Visit(exp1, null); + var key2 = ExpressionKeyVisitor.Visit(exp2, null); + + Assert.That(key1, Is.Not.EqualTo(key2)); + } + } +} diff --git a/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs b/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs index 95a40181595..d5f95c576d5 100644 --- a/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs +++ b/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs @@ -238,7 +238,7 @@ private void VisitMethod(MethodInfo methodInfo) if (methodInfo.IsGenericMethod) { _string.Append('['); - _string.Append(string.Join(",", methodInfo.GetGenericArguments().Select(a => a.FullName).ToArray())); + _string.Append(string.Join(",", methodInfo.GetGenericArguments().Select(a => a.AssemblyQualifiedName).ToArray())); _string.Append(']'); } } From 5b2782cc7d93e2e8b3714c0a9cd8612bbece6d63 Mon Sep 17 00:00:00 2001 From: Marcin Kasperski Date: Tue, 16 Jan 2018 21:58:00 +0100 Subject: [PATCH 2/5] Tweaks after review * Made sure the expression is the same for both types, via common query provider * Added test preconditions * Relocated files to appropriate folders --- src/NHibernate.DomainModel/AnonymousType1.cs | 28 -------------- .../NHSpecific/AnonymousType1.cs | 38 +++++++++++++++++++ .../NHSpecificTest/GH1526/AnonymousType1.cs | 29 +++++++------- .../NHSpecificTest/GH1526/Fixture.cs | 31 +++++++++++---- 4 files changed, 75 insertions(+), 51 deletions(-) delete mode 100644 src/NHibernate.DomainModel/AnonymousType1.cs create mode 100644 src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs diff --git a/src/NHibernate.DomainModel/AnonymousType1.cs b/src/NHibernate.DomainModel/AnonymousType1.cs deleted file mode 100644 index 7a86e60df90..00000000000 --- a/src/NHibernate.DomainModel/AnonymousType1.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; - -// ReSharper disable once CheckNamespace -// Simulates compiler-generated, non-namespaced anonymous type -internal class AnonymousType1 -{ - public T Name { get; set; } -} - -namespace NHibernate.DomainModel -{ - // Produces an Expression that has the above AnonymousType1 embedded in it - public static class AnonymousTypeExpressionProviderFromNHibernateDomainModelAssembly - { - public static Expression GetExpression() - { - Expression>>> exp = () => - Enumerable.Empty() - .Select(c => new AnonymousType1 { Name = c.Name }) - .ToList(); - - return exp; - } - } -} diff --git a/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs b/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs new file mode 100644 index 00000000000..fd218e3331a --- /dev/null +++ b/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; + +// Simulates compiler-generated, non-namespaced anonymous type with one property +internal class AnonymousType1 +{ + public TProp1 Prop1 { get; set; } +} + +namespace NHibernate.DomainModel.NHSpecific +{ + // Produces an Expression that has the above AnonymousType1 embedded in it + public static class AnonymousTypeQueryExpressionProviderFromNHibernateDomainModelAssembly + { + public static System.Type GetAnonymousType() + { + return typeof(AnonymousType1); + } + + public static Expression GetQueryExpression() + { + return TypedSimpleQueryExpressionProvider.GetQueryExpression>(); + } + } + + public static class TypedSimpleQueryExpressionProvider + { + public static Expression GetQueryExpression() where T : new () + { + Expression>> exp = () => + Enumerable.Empty().Select(o => new T()).ToList(); + + return exp; + } + } +} diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs index 90f0afdf460..a79f4300269 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs @@ -1,29 +1,26 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using NHibernate.DomainModel; +using System.Linq.Expressions; +using NHibernate.DomainModel.NHSpecific; -// ReSharper disable once CheckNamespace -// Simulates a compiler-generated, non-namespaced anonymous type -internal class AnonymousType1 +// Simulates a compiler-generated, non-namespaced anonymous type with one property +// Exactly the same as the one in NHibernate.DomainModel.NHSpecific +internal class AnonymousType1 { - public T Name { get; set; } + public TProp1 Prop1 { get; set; } } namespace NHibernate.Test.NHSpecificTest.GH1526 { // Produces an Expression that has the above AnonymousType1 embedded in it - public static class AnonymousTypeExpressionProviderFromNHibernateTestAssembly + public static class AnonymousTypeQueryExpressionProviderFromNHibernateTestAssembly { - public static Expression GetExpression() + public static System.Type GetAnonymousType() { - Expression>>> exp = () => - Enumerable.Empty() - .Select(c => new AnonymousType1 { Name = c.Name }) - .ToList(); + return typeof(AnonymousType1); + } - return exp; + public static Expression GetQueryExpression() + { + return TypedSimpleQueryExpressionProvider.GetQueryExpression>(); } } } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs index bd4db94744f..401ba798f99 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs @@ -1,6 +1,8 @@ -using System; -using NHibernate.DomainModel; +using System.Collections.Generic; +using System.Linq.Expressions; +using NHibernate.DomainModel.NHSpecific; using NHibernate.Linq.Visitors; +using NHibernate.Param; using NUnit.Framework; namespace NHibernate.Test.NHSpecificTest.GH1526 @@ -9,13 +11,28 @@ namespace NHibernate.Test.NHSpecificTest.GH1526 public class Fixture { [Test] - public void ShouldCreateDifferentKeyForAnonymousTypesFromDifferentAssemblies() + public void ShouldCreateDifferentKeyForSameNamedAnonymousTypesFromDifferentAssemblies() { - var exp1 = AnonymousTypeExpressionProviderFromNHibernateTestAssembly.GetExpression(); - var exp2 = AnonymousTypeExpressionProviderFromNHibernateDomainModelAssembly.GetExpression(); + // preconditions of the test + var type1 = AnonymousTypeQueryExpressionProviderFromNHibernateTestAssembly + .GetAnonymousType(); + var type2 = AnonymousTypeQueryExpressionProviderFromNHibernateDomainModelAssembly + .GetAnonymousType(); + + Assert.That(type1.FullName, Is.EqualTo(type2.FullName), + "The two tested types must have the same FullName for demonstrating the bug."); - var key1 = ExpressionKeyVisitor.Visit(exp1, null); - var key2 = ExpressionKeyVisitor.Visit(exp2, null); + Assert.That(type1, Is.Not.EqualTo(type2), + "The two tested types must not be the same for demonstrating the bug."); + + // the test + var exp1 = AnonymousTypeQueryExpressionProviderFromNHibernateTestAssembly + .GetQueryExpression(); + var exp2 = AnonymousTypeQueryExpressionProviderFromNHibernateDomainModelAssembly + .GetQueryExpression(); + + var key1 = ExpressionKeyVisitor.Visit(exp1, new Dictionary()); + var key2 = ExpressionKeyVisitor.Visit(exp2, new Dictionary()); Assert.That(key1, Is.Not.EqualTo(key2)); } From b1890440bc29a5500ae95fc0adf6c921b0b879d1 Mon Sep 17 00:00:00 2001 From: Marcin Kasperski Date: Wed, 17 Jan 2018 02:46:51 +0100 Subject: [PATCH 3/5] Refactored expression providers and tests too allow for more test cases --- .../NHSpecific/AnonymousType1.cs | 28 ++++++++----- .../NHSpecificTest/GH1526/AnonymousType1.cs | 13 +++--- .../NHSpecificTest/GH1526/Fixture.cs | 41 ++++++++++++------- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs b/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs index fd218e3331a..53ceb45382e 100644 --- a/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs +++ b/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -11,26 +10,33 @@ internal class AnonymousType1 namespace NHibernate.DomainModel.NHSpecific { - // Produces an Expression that has the above AnonymousType1 embedded in it - public static class AnonymousTypeQueryExpressionProviderFromNHibernateDomainModelAssembly + public class AnonymousTypeQueryExpressionProviderFromNHibernateDomainModelAssembly { - public static System.Type GetAnonymousType() + private readonly TypedQueryExpressionProvider> _provider + = new TypedQueryExpressionProvider>(); + + public System.Type GetAnonymousType() { - return typeof(AnonymousType1); + return _provider.GetSuppliedType(); } - public static Expression GetQueryExpression() + public Expression GetExpressionOfMethodCall() { - return TypedSimpleQueryExpressionProvider.GetQueryExpression>(); + return _provider.GetExpressionOfMethodCall(); } } - public static class TypedSimpleQueryExpressionProvider + public class TypedQueryExpressionProvider where T : new () { - public static Expression GetQueryExpression() where T : new () + public System.Type GetSuppliedType() + { + return typeof(T); + } + + public Expression GetExpressionOfMethodCall() { - Expression>> exp = () => - Enumerable.Empty().Select(o => new T()).ToList(); + Expression> exp = () => + Enumerable.Empty().Select(o => (T)o).ToList(); return exp; } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs index a79f4300269..5bc9e2e1b0c 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs @@ -11,16 +11,19 @@ internal class AnonymousType1 namespace NHibernate.Test.NHSpecificTest.GH1526 { // Produces an Expression that has the above AnonymousType1 embedded in it - public static class AnonymousTypeQueryExpressionProviderFromNHibernateTestAssembly + public class AnonymousTypeQueryExpressionProviderFromNHibernateTestAssembly { - public static System.Type GetAnonymousType() + private readonly TypedQueryExpressionProvider> _provider + = new TypedQueryExpressionProvider>(); + + public System.Type GetAnonymousType() { - return typeof(AnonymousType1); + return _provider.GetSuppliedType(); } - public static Expression GetQueryExpression() + public Expression GetExpressionOfMethodCall() { - return TypedSimpleQueryExpressionProvider.GetQueryExpression>(); + return _provider.GetExpressionOfMethodCall(); } } } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs index 401ba798f99..d5d50701283 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs @@ -10,31 +10,44 @@ namespace NHibernate.Test.NHSpecificTest.GH1526 [TestFixture] public class Fixture { - [Test] - public void ShouldCreateDifferentKeyForSameNamedAnonymousTypesFromDifferentAssemblies() + private readonly AnonymousTypeQueryExpressionProviderFromNHibernateTestAssembly _providerFromNHTest + = new AnonymousTypeQueryExpressionProviderFromNHibernateTestAssembly(); + + private readonly AnonymousTypeQueryExpressionProviderFromNHibernateDomainModelAssembly _providerFromNHDoMo + = new AnonymousTypeQueryExpressionProviderFromNHibernateDomainModelAssembly(); + + [OneTimeSetUp] + public void OneTimeSetUp() { - // preconditions of the test - var type1 = AnonymousTypeQueryExpressionProviderFromNHibernateTestAssembly - .GetAnonymousType(); - var type2 = AnonymousTypeQueryExpressionProviderFromNHibernateDomainModelAssembly - .GetAnonymousType(); + // all the tests in this fixture run under condition, that + // the types used from the two providers are different, + // but have exactly the same System.Type.FullName when inspected + + var type1 = _providerFromNHTest.GetAnonymousType(); + var type2 = _providerFromNHDoMo.GetAnonymousType(); Assert.That(type1.FullName, Is.EqualTo(type2.FullName), "The two tested types must have the same FullName for demonstrating the bug."); Assert.That(type1, Is.Not.EqualTo(type2), "The two tested types must not be the same for demonstrating the bug."); + } - // the test - var exp1 = AnonymousTypeQueryExpressionProviderFromNHibernateTestAssembly - .GetQueryExpression(); - var exp2 = AnonymousTypeQueryExpressionProviderFromNHibernateDomainModelAssembly - .GetQueryExpression(); + [Test] + public void ShouldCreateDifferentKeys_MethodCallExpression() + { + var exp1 = _providerFromNHTest.GetExpressionOfMethodCall(); + var exp2 = _providerFromNHDoMo.GetExpressionOfMethodCall(); - var key1 = ExpressionKeyVisitor.Visit(exp1, new Dictionary()); - var key2 = ExpressionKeyVisitor.Visit(exp2, new Dictionary()); + var key1 = GetCacheKey(exp1); + var key2 = GetCacheKey(exp2); Assert.That(key1, Is.Not.EqualTo(key2)); } + + private static string GetCacheKey(Expression exp) + { + return ExpressionKeyVisitor.Visit(exp, new Dictionary()); + } } } From 6cf1f388d35c42d5e55cdaeada57dc258c83a099 Mon Sep 17 00:00:00 2001 From: Marcin Kasperski Date: Wed, 17 Jan 2018 02:51:52 +0100 Subject: [PATCH 4/5] Added tests and fix for ExpressionKeyVisitor.VisitNew --- .../NHSpecific/AnonymousType1.cs | 15 +++++++++++++++ .../NHSpecificTest/GH1526/AnonymousType1.cs | 5 +++++ .../NHSpecificTest/GH1526/Fixture.cs | 12 ++++++++++++ .../Linq/Visitors/ExpressionKeyVisitor.cs | 2 +- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs b/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs index 53ceb45382e..1710fe21398 100644 --- a/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs +++ b/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs @@ -24,6 +24,11 @@ public Expression GetExpressionOfMethodCall() { return _provider.GetExpressionOfMethodCall(); } + + public Expression GetExpressionOfNew() + { + return _provider.GetExpressionOfNew(); + } } public class TypedQueryExpressionProvider where T : new () @@ -40,5 +45,15 @@ public Expression GetExpressionOfMethodCall() return exp; } + + public Expression GetExpressionOfNew() + { + // adds .GetHashCode to make sure the .ToList is always of same generic type + // so that the only variable part is the 'new T()' + Expression> exp = () => + Enumerable.Empty().Select(o => new T().GetHashCode()).ToList(); + + return exp; + } } } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs index 5bc9e2e1b0c..5d5414245d7 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs @@ -25,5 +25,10 @@ public Expression GetExpressionOfMethodCall() { return _provider.GetExpressionOfMethodCall(); } + + public Expression GetExpressionOfNew() + { + return _provider.GetExpressionOfNew(); + } } } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs index d5d50701283..b6f2adec71b 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs @@ -45,6 +45,18 @@ public void ShouldCreateDifferentKeys_MethodCallExpression() Assert.That(key1, Is.Not.EqualTo(key2)); } + [Test] + public void ShouldCreateDifferentKeys_NewExpression() + { + var exp1 = _providerFromNHTest.GetExpressionOfNew(); + var exp2 = _providerFromNHDoMo.GetExpressionOfNew(); + + var key1 = GetCacheKey(exp1); + var key2 = GetCacheKey(exp2); + + Assert.That(key1, Is.Not.EqualTo(key2)); + } + private static string GetCacheKey(Expression exp) { return ExpressionKeyVisitor.Visit(exp, new Dictionary()); diff --git a/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs b/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs index d5f95c576d5..c1558199e4b 100644 --- a/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs +++ b/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs @@ -190,7 +190,7 @@ protected override Expression VisitMethodCall(MethodCallExpression expression) protected override Expression VisitNew(NewExpression expression) { _string.Append("new "); - _string.Append(expression.Constructor.DeclaringType.Name); + _string.Append(expression.Constructor.DeclaringType.AssemblyQualifiedName); _string.Append('('); Visit(expression.Arguments, AppendCommas); _string.Append(')'); From 2b6a677c535303693d3e5b99443646b8ce769be0 Mon Sep 17 00:00:00 2001 From: Marcin Kasperski Date: Wed, 17 Jan 2018 02:55:49 +0100 Subject: [PATCH 5/5] Added tests and fix for ExpressionKeyVisitor.VisitTypeBinary --- .../NHSpecific/AnonymousType1.cs | 13 +++++++++++++ .../NHSpecificTest/GH1526/AnonymousType1.cs | 5 +++++ .../NHSpecificTest/GH1526/Fixture.cs | 12 ++++++++++++ .../Linq/Visitors/ExpressionKeyVisitor.cs | 4 ++-- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs b/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs index 1710fe21398..72c4161b197 100644 --- a/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs +++ b/src/NHibernate.DomainModel/NHSpecific/AnonymousType1.cs @@ -29,6 +29,11 @@ public Expression GetExpressionOfNew() { return _provider.GetExpressionOfNew(); } + + public Expression GetExpressionOfTypeBinary() + { + return _provider.GetExpressionOfTypeBinary(); + } } public class TypedQueryExpressionProvider where T : new () @@ -55,5 +60,13 @@ public Expression GetExpressionOfNew() return exp; } + + public Expression GetExpressionOfTypeBinary() + { + Expression> exp = () => + Enumerable.Empty().Select(o => o is T).ToList(); + + return exp; + } } } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs index 5d5414245d7..9c7d606c998 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/AnonymousType1.cs @@ -30,5 +30,10 @@ public Expression GetExpressionOfNew() { return _provider.GetExpressionOfNew(); } + + public Expression GetExpressionOfTypeBinary() + { + return _provider.GetExpressionOfTypeBinary(); + } } } diff --git a/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs index b6f2adec71b..5318d771ec2 100644 --- a/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs +++ b/src/NHibernate.Test/NHSpecificTest/GH1526/Fixture.cs @@ -57,6 +57,18 @@ public void ShouldCreateDifferentKeys_NewExpression() Assert.That(key1, Is.Not.EqualTo(key2)); } + [Test] + public void ShouldCreateDifferentKeys_TypeBinaryExpression() + { + var exp1 = _providerFromNHTest.GetExpressionOfTypeBinary(); + var exp2 = _providerFromNHDoMo.GetExpressionOfTypeBinary(); + + var key1 = GetCacheKey(exp1); + var key2 = GetCacheKey(exp2); + + Assert.That(key1, Is.Not.EqualTo(key2)); + } + private static string GetCacheKey(Expression exp) { return ExpressionKeyVisitor.Visit(exp, new Dictionary()); diff --git a/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs b/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs index c1558199e4b..733a7fe04e2 100644 --- a/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs +++ b/src/NHibernate/Linq/Visitors/ExpressionKeyVisitor.cs @@ -210,7 +210,7 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression expression) _string.Append("IsType("); Visit(expression.Expression); _string.Append(", "); - _string.Append(expression.TypeOperand.FullName); + _string.Append(expression.TypeOperand.AssemblyQualifiedName); _string.Append(")"); return expression; @@ -243,4 +243,4 @@ private void VisitMethod(MethodInfo methodInfo) } } } -} \ No newline at end of file +}