diff --git a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs
index 0a32c0da..7a487fe8 100644
--- a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs
+++ b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs
@@ -697,7 +697,7 @@ public static IQueryable GroupJoin([NotNull] this IQueryable outer, [CanBeNull]
typeof(Queryable), nameof(Queryable.GroupJoin),
new[] { outer.ElementType, innerType, outerSelectorLambda.Body.Type, resultSelectorLambda.Body.Type },
outer.Expression,
- Expression.Constant(inner),
+ inner.AsQueryable().Expression,
Expression.Quote(outerSelectorLambda),
Expression.Quote(innerSelectorLambda),
Expression.Quote(resultSelectorLambda)));
diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
index 591fac4f..2b22e203 100644
--- a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
@@ -1549,6 +1549,10 @@ Type FindType(string name)
{
return _root.Type;
}
+ if (this._parsingConfig.AllowNewToEvaluateAnyType && Type.GetType(name) != null)
+ {
+ return Type.GetType(name);
+ }
return null;
}
diff --git a/src/System.Linq.Dynamic.Core/ParsingConfig.cs b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
index cc0414a5..59bae863 100644
--- a/src/System.Linq.Dynamic.Core/ParsingConfig.cs
+++ b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
@@ -1,4 +1,5 @@
using System.Linq.Dynamic.Core.CustomTypeProviders;
+using System.Reflection;
namespace System.Linq.Dynamic.Core
{
@@ -7,6 +8,26 @@ namespace System.Linq.Dynamic.Core
///
public class ParsingConfig
{
+ ///
+ /// Get an instance of ParsingConfig
+ ///
+ public ParsingConfig()
+ {
+#if !(DOTNET5_1 || WINDOWS_APP || UAP10_0 || NETSTANDARD)
+ AppDomain.CurrentDomain.TypeResolve += this.CurrentDomain_TypeResolve;
+#endif
+ }
+
+ ///
+ /// Cleanup
+ ///
+ ~ParsingConfig()
+ {
+#if !(DOTNET5_1 || WINDOWS_APP || UAP10_0 || NETSTANDARD)
+ AppDomain.CurrentDomain.TypeResolve -= this.CurrentDomain_TypeResolve;
+#endif
+ }
+
///
/// Default ParsingConfig
///
@@ -62,5 +83,35 @@ public IDynamicLinkCustomTypeProvider CustomTypeProvider
/// See https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.1#linq-groupby-translation
///
public bool EvaluateGroupByAtDatabase { get; set; }
+
+ ///
+ /// Allows the New() keyword to evaluate any available Type
+ ///
+ public bool AllowNewToEvaluateAnyType { get; set; } = false;
+
+#if !(DOTNET5_1 || WINDOWS_APP || UAP10_0 || NETSTANDARD)
+ ///
+ /// Custom type resolver to allow ExpressionParser to find any type
+ /// registered in the current application domain. You can add additional
+ /// type resolvers in your application.
+ ///
+ ///
+ ///
+ ///
+ protected Assembly CurrentDomain_TypeResolve(object sender, ResolveEventArgs args)
+ {
+ foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
+ {
+ Type t = assembly.GetType(args.Name, false, true);
+
+ if (t != null)
+ {
+ return assembly;
+ }
+ }
+
+ return null;
+ }
+#endif
}
}
diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
index 41210139..32163f8a 100644
--- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
@@ -169,6 +169,16 @@ public class Example
public DayOfWeek DOW { get; set; }
public int Sec { get; set; }
public int? SecNull { get; set; }
+
+ public class NestedDto
+ {
+ public string Name { get; set; }
+
+ public class NestedDto2
+ {
+ public string Name2 { get; set; }
+ }
+ }
}
public class ExampleWithConstructor
@@ -227,6 +237,47 @@ public void Select_Dynamic_IntoTypeWithNullableProperties2()
Check.That(resultDynamic.Last()).Equals(result.Last());
}
+ [Fact]
+ public void Select_Dynamic_IntoKnownNestedType()
+ {
+
+#if (DOTNET5_1 || WINDOWS_APP || UAP10_0 || NETSTANDARD)
+ return;
+#endif
+ var config = new ParsingConfig();
+ config.AllowNewToEvaluateAnyType = true;
+
+ // Act
+ IQueryable data = new List() { "name1", "name2" }.AsQueryable();
+ IQueryable projectedData =
+ (IQueryable) data.Select(config, $"new {typeof(Example.NestedDto).FullName}(~ as Name)");
+
+ // Assert
+ Check.That(projectedData.First().Name).Equals("name1");
+ Check.That(projectedData.Last().Name).Equals("name2");
+ }
+
+ [Fact]
+ public void Select_Dynamic_IntoKnownNestedTypeSecondLevel()
+ {
+
+#if (DOTNET5_1 || WINDOWS_APP || UAP10_0 || NETSTANDARD)
+ return;
+#endif
+
+ var config = new ParsingConfig();
+ config.AllowNewToEvaluateAnyType = true;
+
+ // Act
+ IQueryable data = new List() { "name1", "name2" }.AsQueryable();
+ IQueryable projectedData =
+ (IQueryable)data.Select(config, $"new {typeof(Example.NestedDto.NestedDto2).FullName}(~ as Name2)");
+
+ // Assert
+ Check.That(projectedData.First().Name2).Equals("name1");
+ Check.That(projectedData.Last().Name2).Equals("name2");
+ }
+
[Fact]
public void Select_Dynamic_Exceptions()
{