diff --git a/src/System.Linq.Dynamic.Core/CustomTypeProviders/AbstractDynamicLinqCustomTypeProvider.cs b/src/System.Linq.Dynamic.Core/CustomTypeProviders/AbstractDynamicLinqCustomTypeProvider.cs
index 3f54beed9..cccb56c48 100644
--- a/src/System.Linq.Dynamic.Core/CustomTypeProviders/AbstractDynamicLinqCustomTypeProvider.cs
+++ b/src/System.Linq.Dynamic.Core/CustomTypeProviders/AbstractDynamicLinqCustomTypeProvider.cs
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-using System.Linq.Dynamic.Core.Extensions;
using System.Linq.Dynamic.Core.Validation;
using System.Reflection;
@@ -13,11 +12,25 @@ namespace System.Linq.Dynamic.Core.CustomTypeProviders;
public abstract class AbstractDynamicLinqCustomTypeProvider
{
///
- /// Finds the unique types marked with DynamicLinqTypeAttribute.
+ /// Additional types which should also be resolved.
+ ///
+ protected readonly IList AdditionalTypes;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A list of additional types (without the DynamicLinqTypeAttribute annotation) which should also be resolved.
+ protected AbstractDynamicLinqCustomTypeProvider(IList additionalTypes)
+ {
+ AdditionalTypes = Check.NotNull(additionalTypes);
+ }
+
+ ///
+ /// Finds the unique types annotated with DynamicLinqTypeAttribute.
///
/// The assemblies to process.
///
- protected IEnumerable FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumerable assemblies)
+ protected Type[] FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumerable assemblies)
{
Check.NotNull(assemblies);
#if !NET35
@@ -27,7 +40,7 @@ protected IEnumerable FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumera
}
///
- /// Resolve any type which is registered in the current application domain.
+ /// Resolve a type which is annotated with DynamicLinqTypeAttribute or when the type is listed in AdditionalTypes.
///
/// The assemblies to inspect.
/// The typename to resolve.
@@ -37,20 +50,13 @@ protected IEnumerable FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumera
Check.NotNull(assemblies);
Check.NotEmpty(typeName);
- foreach (var assembly in assemblies)
- {
- var resolvedType = assembly.GetType(typeName, false, true);
- if (resolvedType != null)
- {
- return resolvedType;
- }
- }
-
- return null;
+ var types = FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies).Union(AdditionalTypes);
+ return types.FirstOrDefault(t => t.FullName == typeName);
}
///
- /// Resolve a type by the simple name which is registered in the current application domain.
+ /// Resolve a type which is annotated with DynamicLinqTypeAttribute by the simple (short) name.
+ /// Also when the type is listed in AdditionalTypes.
///
/// The assemblies to inspect.
/// The simple typename to resolve.
@@ -60,22 +66,16 @@ protected IEnumerable FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumera
Check.NotNull(assemblies);
Check.NotEmpty(simpleTypeName);
- foreach (var assembly in assemblies)
- {
- var fullNames = assembly.GetTypes().Select(t => t.FullName!).Distinct();
- var firstMatchingFullname = fullNames.FirstOrDefault(fn => fn.EndsWith($".{simpleTypeName}"));
+ var types = FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies);
+ var fullNames = types.Select(t => t.FullName!).Distinct().ToArray();
+ var firstMatchingFullname = fullNames.FirstOrDefault(fn => fn.EndsWith($".{simpleTypeName}"));
- if (firstMatchingFullname != null)
- {
- var resolvedType = assembly.GetType(firstMatchingFullname, false, true);
- if (resolvedType != null)
- {
- return resolvedType;
- }
- }
+ if (firstMatchingFullname == null)
+ {
+ return null;
}
- return null;
+ return types.FirstOrDefault(t => t.FullName == firstMatchingFullname);
}
#if (UAP10_0 || NETSTANDARD)
@@ -147,7 +147,7 @@ protected Type[] GetAssemblyTypesWithDynamicLinqTypeAttribute(IEnumerable().ToArray();
}
catch
{
diff --git a/src/System.Linq.Dynamic.Core/CustomTypeProviders/DefaultDynamicLinqCustomTypeProvider.cs b/src/System.Linq.Dynamic.Core/CustomTypeProviders/DefaultDynamicLinqCustomTypeProvider.cs
index f69c9c49f..0e4da9b6f 100644
--- a/src/System.Linq.Dynamic.Core/CustomTypeProviders/DefaultDynamicLinqCustomTypeProvider.cs
+++ b/src/System.Linq.Dynamic.Core/CustomTypeProviders/DefaultDynamicLinqCustomTypeProvider.cs
@@ -10,8 +10,6 @@ namespace System.Linq.Dynamic.Core.CustomTypeProviders;
///
/// Scans the current AppDomain for all types marked with , and adds them as custom Dynamic Link types.
///
-/// Also provides functionality to resolve a Type in the current Application Domain.
-///
/// This class is used as default for full .NET Framework and .NET Core App 2.x and higher.
///
public class DefaultDynamicLinqCustomTypeProvider : AbstractDynamicLinqCustomTypeProvider, IDynamicLinkCustomTypeProvider
@@ -22,12 +20,12 @@ public class DefaultDynamicLinqCustomTypeProvider : AbstractDynamicLinqCustomTyp
private HashSet? _cachedCustomTypes;
private Dictionary>? _cachedExtensionMethods;
- ///
+ ///
/// Initializes a new instance of the class.
/// Backwards compatibility for issue https://github.com/zzzprojects/System.Linq.Dynamic.Core/issues/830.
///
/// Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to 'true'.
- [Obsolete("Please use the DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, bool cacheCustomTypes = true) constructor.")]
+ [Obsolete("Please use the DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, IList additionalTypes, bool cacheCustomTypes = true) constructor.")]
public DefaultDynamicLinqCustomTypeProvider(bool cacheCustomTypes = true) : this(ParsingConfig.Default, cacheCustomTypes)
{
}
@@ -37,7 +35,17 @@ public DefaultDynamicLinqCustomTypeProvider(bool cacheCustomTypes = true) : this
///
/// The parsing configuration.
/// Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to 'true'.
- public DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, bool cacheCustomTypes = true)
+ public DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, bool cacheCustomTypes = true) : this(config, new List(), cacheCustomTypes)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The parsing configuration.
+ /// A list of additional types (without the DynamicLinqTypeAttribute annotation) which should also be resolved.
+ /// Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to 'true'.
+ public DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, IList additionalTypes, bool cacheCustomTypes = true) : base(additionalTypes)
{
_assemblyHelper = new DefaultAssemblyHelper(Check.NotNull(config));
_cacheCustomTypes = cacheCustomTypes;
@@ -96,7 +104,8 @@ public Dictionary> GetExtensionMethods()
private HashSet GetCustomTypesInternal()
{
IEnumerable assemblies = _assemblyHelper.GetAssemblies();
- return new HashSet(FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies));
+ var types = FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies).Union(AdditionalTypes);
+ return new HashSet(types);
}
private Dictionary> GetExtensionMethodsInternal()
diff --git a/src/System.Linq.Dynamic.Core/CustomTypeProviders/IDynamicLinkCustomTypeProvider.cs b/src/System.Linq.Dynamic.Core/CustomTypeProviders/IDynamicLinkCustomTypeProvider.cs
index 83fde4940..ff8e85ff8 100644
--- a/src/System.Linq.Dynamic.Core/CustomTypeProviders/IDynamicLinkCustomTypeProvider.cs
+++ b/src/System.Linq.Dynamic.Core/CustomTypeProviders/IDynamicLinkCustomTypeProvider.cs
@@ -2,9 +2,9 @@
{
///
/// Interface for providing functionality to find custom types for or resolve any type.
- /// Note that this interface will be marked obsolete in the next version. Use instead.
///
+ [Obsolete("Please use the IDynamicLinqCustomTypeProvider interface instead.")]
public interface IDynamicLinkCustomTypeProvider : IDynamicLinqCustomTypeProvider
{
}
-}
+}
\ No newline at end of file
diff --git a/src/System.Linq.Dynamic.Core/Extensions/LinqExtensions.cs b/src/System.Linq.Dynamic.Core/Extensions/LinqExtensions.cs
deleted file mode 100644
index dc563fa8c..000000000
--- a/src/System.Linq.Dynamic.Core/Extensions/LinqExtensions.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq.Dynamic.Core.Validation;
-
-namespace System.Linq.Dynamic.Core.Extensions;
-
-[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
-internal static class LinqExtensions
-{
- public static IEnumerable WhereNotNull(this IEnumerable sequence)
- {
- Check.NotNull(sequence);
-
- return sequence.Where(e => e != null)!;
- }
-}
\ No newline at end of file
diff --git a/src/System.Linq.Dynamic.Core/Parser/PredefinedTypesHelper.cs b/src/System.Linq.Dynamic.Core/Parser/PredefinedTypesHelper.cs
index 58cb5f640..e43d676bf 100644
--- a/src/System.Linq.Dynamic.Core/Parser/PredefinedTypesHelper.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/PredefinedTypesHelper.cs
@@ -28,7 +28,7 @@ internal static class PredefinedTypesHelper
public static readonly IDictionary PredefinedTypes = new ConcurrentDictionary(new Dictionary
{
- { typeof(object), 0 },
+ // { typeof(object), 0 }, Removed because of CVE-2024-51417
{ typeof(bool), 0 },
{ typeof(char), 0 },
{ typeof(string), 0 },
diff --git a/src/System.Linq.Dynamic.Core/ParsingConfig.cs b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
index 70acd35cc..4886577b3 100644
--- a/src/System.Linq.Dynamic.Core/ParsingConfig.cs
+++ b/src/System.Linq.Dynamic.Core/ParsingConfig.cs
@@ -71,6 +71,25 @@ public IDynamicLinkCustomTypeProvider? CustomTypeProvider
}
}
+ ///
+ /// Sets the CustomTypeProvider to .
+ ///
+ /// Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to true.
+ public void UseDefaultDynamicLinqCustomTypeProvider(bool cacheCustomTypes = true)
+ {
+ _customTypeProvider = new DefaultDynamicLinqCustomTypeProvider(this, cacheCustomTypes);
+ }
+
+ ///
+ /// Sets the CustomTypeProvider to .
+ ///
+ /// Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to true.
+ /// A list of additional types (without the DynamicLinqTypeAttribute annotation) which should also be resolved.
+ public void UseDefaultDynamicLinqCustomTypeProvider(IList additionalTypes, bool cacheCustomTypes = true)
+ {
+ _customTypeProvider = new DefaultDynamicLinqCustomTypeProvider(this, additionalTypes, cacheCustomTypes);
+ }
+
///
/// Load additional assemblies from the current domain base directory.
/// Note: only used when full .NET Framework and .NET Core App 2.x and higher.
diff --git a/test/System.Linq.Dynamic.Core.Tests/CustomTypeProviders/DefaultDynamicLinqCustomTypeProviderTests.cs b/test/System.Linq.Dynamic.Core.Tests/CustomTypeProviders/DefaultDynamicLinqCustomTypeProviderTests.cs
index 6fe19ba87..1b9867b0d 100644
--- a/test/System.Linq.Dynamic.Core.Tests/CustomTypeProviders/DefaultDynamicLinqCustomTypeProviderTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/CustomTypeProviders/DefaultDynamicLinqCustomTypeProviderTests.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using System.Collections.Generic;
+using System.IO;
using System.Linq.Dynamic.Core.CustomTypeProviders;
using FluentAssertions;
using NFluent;
@@ -8,11 +9,17 @@ namespace System.Linq.Dynamic.Core.Tests.CustomTypeProviders;
public class DefaultDynamicLinqCustomTypeProviderTests
{
+ private readonly IList _additionalTypes = new List
+ {
+ typeof(DirectoryInfo),
+ typeof(DefaultDynamicLinqCustomTypeProviderTests)
+ };
+
private readonly DefaultDynamicLinqCustomTypeProvider _sut;
public DefaultDynamicLinqCustomTypeProviderTests()
{
- _sut = new DefaultDynamicLinqCustomTypeProvider(ParsingConfig.Default);
+ _sut = new DefaultDynamicLinqCustomTypeProvider(ParsingConfig.Default, _additionalTypes);
}
[Fact]
diff --git a/test/System.Linq.Dynamic.Core.Tests/DynamicClassTest.cs b/test/System.Linq.Dynamic.Core.Tests/DynamicClassTest.cs
index ab8bd2894..c020cb94a 100644
--- a/test/System.Linq.Dynamic.Core.Tests/DynamicClassTest.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/DynamicClassTest.cs
@@ -281,7 +281,8 @@ public void DynamicClassArray_Issue593_Fails()
isValid.Should().BeFalse(); // This should actually be true, but fails. For solution see Issue593_Solution1 and Issue593_Solution2.
}
- [SkipIfGitHubActions]
+ // [SkipIfGitHubActions]
+ [Fact(Skip = "867")]
public void DynamicClassArray_Issue593_Solution1()
{
// Arrange
diff --git a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs
index a0895cc5b..9260cf8d7 100644
--- a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs
@@ -1058,7 +1058,7 @@ public void DynamicExpressionParser_ParseLambda_StringLiteral_QuotationMark()
Assert.Equal(expectedRightValue, rightValue);
}
- [Fact]
+ [Fact(Skip = "867")]
public void DynamicExpressionParser_ParseLambda_TupleToStringMethodCall_ReturnsStringLambdaExpression()
{
var expression = DynamicExpressionParser.ParseLambda(
diff --git a/test/System.Linq.Dynamic.Core.Tests/Entities/Worker.cs b/test/System.Linq.Dynamic.Core.Tests/Entities/Worker.cs
index 4d5475a35..77bfd548e 100644
--- a/test/System.Linq.Dynamic.Core.Tests/Entities/Worker.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Entities/Worker.cs
@@ -1,5 +1,8 @@
-namespace System.Linq.Dynamic.Core.Tests.Entities
+using System.Linq.Dynamic.Core.CustomTypeProviders;
+
+namespace System.Linq.Dynamic.Core.Tests.Entities
{
+ [DynamicLinqType]
public class Worker : BaseEmployee
{
public string Other { get; set; }
diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
index 42b5a743d..74abc9cd7 100644
--- a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
@@ -13,6 +13,7 @@
namespace System.Linq.Dynamic.Core.Tests
{
+ [DynamicLinqType]
public enum TestEnumPublic : sbyte
{
Var1 = 0,
@@ -25,6 +26,7 @@ public enum TestEnumPublic : sbyte
public partial class ExpressionTests
{
+ [DynamicLinqType]
public enum TestEnum2 : sbyte
{
Var1 = 0,
@@ -919,6 +921,9 @@ public void ExpressionTests_Enum_Property_Equality_Using_PublicEnum_And_FullName
public void ExpressionTests_Enum_Property_Equality_Using_Enum_And_FullName_Inline()
{
// Arrange
+ var config = new ParsingConfig();
+ config.UseDefaultDynamicLinqCustomTypeProvider([typeof(TestEnum2)]);
+
var qry = new List { new TestEnumClass { B = TestEnum2.Var2 } }.AsQueryable();
string enumType = typeof(TestEnum2).FullName!;
@@ -948,7 +953,7 @@ public void ExpressionTests_Enum_Property_Equality_Using_PublicEnum_Name_Inline(
}
[Fact]
- public void ExpressionTests_Enum_Property_Equality_Using_Enum_Name_Inline_Should_Throw_Exception()
+ public void ExpressionTests_Enum_Property_Equality_Using_Enum_Name_Inline_ShouldBeOk()
{
// Arrange
var config = new ParsingConfig
@@ -962,7 +967,7 @@ public void ExpressionTests_Enum_Property_Equality_Using_Enum_Name_Inline_Should
Action a = () => qry.Where(config, $"{enumType}.Var2 == it.B").ToDynamicArray();
// Assert
- a.Should().Throw();
+ a.Should().NotThrow();
}
[Fact]
@@ -1031,7 +1036,10 @@ public void ExpressionTests_Enum_NullableProperty()
[Fact]
public void ExpressionTests_Enum_MoreTests()
{
- var config = new ParsingConfig();
+ var config = new ParsingConfig
+ {
+ ResolveTypesBySimpleName = true
+ };
// Arrange
var lst = new List { TestEnum.Var1, TestEnum.Var2, TestEnum.Var3, TestEnum.Var4, TestEnum.Var5, TestEnum.Var6 };
diff --git a/test/System.Linq.Dynamic.Core.Tests/Helpers/Models/AppSettings.cs b/test/System.Linq.Dynamic.Core.Tests/Helpers/Models/AppSettings.cs
new file mode 100644
index 000000000..260ffef25
--- /dev/null
+++ b/test/System.Linq.Dynamic.Core.Tests/Helpers/Models/AppSettings.cs
@@ -0,0 +1,45 @@
+using System.Collections.Generic;
+using System.Linq.Dynamic.Core.CustomTypeProviders;
+
+namespace System.Linq.Dynamic.Core.Tests.Helpers.Models
+{
+ public static class AppSettings
+ {
+ public static Dictionary SettingsProp { get; } = new()
+ {
+ { "jwt", "test" }
+ };
+
+ public static Dictionary SettingsField = new()
+ {
+ { "jwt", "test" }
+ };
+ }
+
+ [DynamicLinqType]
+ public static class AppSettings2
+ {
+ public static Dictionary SettingsProp { get; } = new()
+ {
+ { "jwt", "test" }
+ };
+
+ public static Dictionary SettingsField = new()
+ {
+ { "jwt", "test" }
+ };
+ }
+
+ public class AppSettings3
+ {
+ public static Dictionary SettingsProp { get; } = new()
+ {
+ { "jwt", "test" }
+ };
+
+ public static Dictionary SettingsField = new()
+ {
+ { "jwt", "test" }
+ };
+ }
+}
\ No newline at end of file
diff --git a/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs
index 22283e6ba..644f6ef1e 100644
--- a/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs
@@ -346,7 +346,7 @@ public void Parse_NullableShouldReturnNullable(string expression, object resultT
[Theory]
[InlineData("it.MainCompany.Name != null", "(company.MainCompany.Name != null)")]
[InlineData("@MainCompany.Companies.Count() > 0", "(company.MainCompany.Companies.Count() > 0)")]
- [InlineData("Company.Equals(null, null)", "Equals(null, null)")]
+ // [InlineData("Company.Equals(null, null)", "Equals(null, null)")] issue 867
[InlineData("MainCompany.Name", "company.MainCompany.Name")]
[InlineData("Name", "company.Name")]
[InlineData("company.Name", "company.Name")]
diff --git a/test/System.Linq.Dynamic.Core.Tests/Parser/MethodFinderTest.cs b/test/System.Linq.Dynamic.Core.Tests/Parser/MethodFinderTest.cs
index a1afadd49..c4b318e1e 100644
--- a/test/System.Linq.Dynamic.Core.Tests/Parser/MethodFinderTest.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/Parser/MethodFinderTest.cs
@@ -7,14 +7,14 @@ namespace System.Linq.Dynamic.Core.Tests.Parser;
public class MethodFinderTest
{
- [Fact]
+ [Fact(Skip = "867")]
public void MethodsOfDynamicLinqAndSystemLinqShouldBeEqual()
{
Expression> expr = x => x.ToString();
var selector = "ToString()";
var prm = Parameter(typeof(int?));
- var parser = new ExpressionParser(new[] { prm }, selector, new object[] { }, ParsingConfig.Default);
+ var parser = new ExpressionParser([prm], selector, [], ParsingConfig.Default);
var expr1 = parser.Parse(null);
Assert.Equal(((MethodCallExpression)expr.Body).Method.DeclaringType, ((MethodCallExpression)expr1).Method.DeclaringType);
diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Is,OfType,As,Cast.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Is,OfType,As,Cast.cs
index 93e7c1e92..1b41ad25f 100644
--- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Is,OfType,As,Cast.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Is,OfType,As,Cast.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Linq.Dynamic.Core.CustomTypeProviders;
using System.Linq.Dynamic.Core.Exceptions;
using System.Linq.Dynamic.Core.Tests.Entities;
using FluentAssertions;
@@ -98,6 +99,7 @@ public void OfType_Dynamic_WithFullName_UseParameterizedNamesInDynamicQuery(bool
internal class Base { }
+ [DynamicLinqType]
internal class DerivedA : Base { }
internal class DerivedB : Base { }
@@ -294,7 +296,8 @@ public void As_Dynamic_ActingOnProperty_NullableInt()
countAsDynamic.Should().Be(count);
}
- public enum TestEnum
+ [DynamicLinqType]
+ public enum TestEnumForThisTest
{
None = 0,
@@ -305,10 +308,10 @@ public enum TestEnum
public void As_Dynamic_ActingOnProperty_NullableEnum()
{
// Assign
- var nullableEnumType = $"{typeof(TestEnum).FullName}?";
+ var nullableEnumType = $"{typeof(TestEnumForThisTest).FullName}?";
var qry = new[]
{
- new { Value = TestEnum.X }
+ new { Value = TestEnumForThisTest.X }
}.AsQueryable();
// Act
@@ -365,7 +368,10 @@ public void As_Dynamic_ActingOnProperty_WithType()
countAsDynamic.Should().Be(1);
}
+ [DynamicLinqType]
public class AS_A { }
+
+ [DynamicLinqType]
public class AS_B : AS_A
{
public string MyProperty { get; set; }
diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
index f1d3a428f..0383b1c29 100644
--- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs
@@ -1,6 +1,7 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
+using System.Linq.Dynamic.Core.CustomTypeProviders;
using System.Linq.Dynamic.Core.Exceptions;
using System.Linq.Dynamic.Core.Tests.Helpers.Models;
using FluentAssertions;
@@ -19,6 +20,7 @@ namespace System.Linq.Dynamic.Core.Tests
{
public partial class QueryableTests
{
+ [DynamicLinqType]
public class Example
{
public int Field;
@@ -29,10 +31,12 @@ public class Example
public int Sec { get; set; }
public int? SecNull { get; set; }
+ [DynamicLinqType]
public class NestedDto
{
public string Name { get; set; }
+ [DynamicLinqType]
public class NestedDto2
{
public string Name2 { get; set; }
@@ -324,7 +328,11 @@ public void Select_Dynamic_IntoTypeWithNullableParameterInConstructor()
public void Select_Dynamic_SystemType1()
{
// Arrange
- var config = new ParsingConfig { AllowNewToEvaluateAnyType = true };
+ var config = new ParsingConfig
+ {
+ AllowNewToEvaluateAnyType = true
+ };
+ config.UseDefaultDynamicLinqCustomTypeProvider([typeof(DirectoryInfo)]);
var queryable = new[] { "test" }.AsQueryable();
// Act
diff --git a/test/System.Linq.Dynamic.Core.Tests/SecurityTests.cs b/test/System.Linq.Dynamic.Core.Tests/SecurityTests.cs
index 77fa0c762..a16f259af 100644
--- a/test/System.Linq.Dynamic.Core.Tests/SecurityTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/SecurityTests.cs
@@ -1,6 +1,5 @@
using System.IO;
using System.Linq.Dynamic.Core.Exceptions;
-using System.Net;
using System.Reflection;
using FluentAssertions;
using Xunit;
@@ -26,13 +25,13 @@ public void MethodsShouldOnlyBeCallableOnPredefinedTypes_Test1()
{
// Arrange
var baseQuery = new[] { 1, 2, 3 }.AsQueryable();
- string predicate = "\"\".GetType().Assembly.DefinedTypes.Where(it.name == \"Assembly\").First().DeclaredMethods.Where(it.Name == \"GetName\").First().Invoke(\"\".GetType().Assembly, new Object[] {} ).Name.ToString() != \"Test\"";
+ var predicate = "\"\".GetType().Assembly.DefinedTypes.Where(it.name == \"Assembly\").First().DeclaredMethods.Where(it.Name == \"GetName\").First().Invoke(\"\".GetType().Assembly, new Object[] {} ).Name.ToString() != \"Test\"";
// Act
Action action = () => baseQuery.OrderBy(predicate);
// Assert
- action.Should().Throw().WithMessage("Methods on type 'MethodBase' are not accessible");
+ action.Should().Throw().WithMessage("Methods on type 'Object' are not accessible");
}
[Fact]
@@ -41,8 +40,7 @@ public void MethodsShouldOnlyBeCallableOnPredefinedTypes_Test2()
// Arrange
var messages = new[]
{
- new Message("Alice", "Bob"),
- new Message("Bob", "Alice")
+ new Message("Alice", "Bob")
}.AsQueryable();
Action action = () => messages.Where(
@@ -50,7 +48,7 @@ public void MethodsShouldOnlyBeCallableOnPredefinedTypes_Test2()
);
// Assert
- action.Should().Throw().WithMessage($"Methods on type 'Assembly' are not accessible");
+ action.Should().Throw().WithMessage($"Methods on type 'Object' are not accessible");
}
[Theory]
@@ -64,4 +62,129 @@ public void DynamicExpressionParser_ParseLambda_IllegalMethodCall_ThrowsExceptio
// Assert
action.Should().Throw().WithMessage($"Methods on type '{type}' are not accessible");
}
+
+ [Theory]
+ [InlineData("c => string.Join(\"_\", c.GetType().Assembly.DefinedTypes.SelectMany(t => t.CustomAttributes).Select(a => a.AttributeType).Select(t => t.AssemblyQualifiedName))")]
+ [InlineData("c => string.Join(\"_\", c.GetType().Assembly.DefinedTypes.Select(t => t.BaseType).Select(t => t.AssemblyQualifiedName))")]
+ [InlineData("c => string.Join(\"_\", c.GetType().Assembly.FullName))")]
+ public void UsingSystemReflectionAssembly_ThrowsException(string selector)
+ {
+ // Arrange
+ var queryable = new[]
+ {
+ new Message("Alice", "Bob")
+ }.AsQueryable();
+
+ // Act
+ Action action = () => queryable.Select(selector);
+
+ // Assert
+ action.Should().Throw().WithMessage("Methods on type 'Object' are not accessible");
+ }
+
+ [Theory]
+ [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsProp[\"jwt\"]")]
+ [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsField[\"jwt\"]")]
+ [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsProp[\"jwt\"]")]
+ [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsField[\"jwt\"]")]
+ public void UsingStaticClassAsType_ThrowsException(string selector)
+ {
+ // Arrange
+ var queryable = new[]
+ {
+ new Message("Alice", "Bob")
+ }.AsQueryable();
+
+ // Act
+ Action action = () => queryable.Select(selector);
+
+ // Assert
+ action.Should().Throw().WithMessage("Type 'System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings' not found");
+ }
+
+ [Theory]
+ [InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3().SettingsProp[\"jwt\"]")]
+ [InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3().SettingsField[\"jwt\"]")]
+ [InlineData("c => new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3().SettingsProp[\"jwt\"]")]
+ [InlineData("c => new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3().SettingsField[\"jwt\"]")]
+ public void UsingClassAsType_ThrowsException(string selector)
+ {
+ // Arrange
+ var queryable = new[]
+ {
+ new Message("Alice", "Bob")
+ }.AsQueryable();
+
+ // Act
+ Action action = () => queryable.Select(selector);
+
+ // Assert
+ action.Should().Throw().WithMessage("Type 'System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3' not found");
+ }
+
+ [Theory]
+ [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsProp[\"jwt\"]")]
+ [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsField[\"jwt\"]")]
+ [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsProp[\"jwt\"]")]
+ [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsField[\"jwt\"]")]
+ public void UsingStaticClassAsType_WhenAddedToDefaultDynamicLinqCustomTypeProvider_ShouldBeOk(string selector)
+ {
+ // Arrange
+ var config = new ParsingConfig();
+ config.UseDefaultDynamicLinqCustomTypeProvider([typeof(Helpers.Models.AppSettings), typeof(Helpers.Models.AppSettings3)]);
+
+ var queryable = new[]
+ {
+ new Message("Alice", "Bob")
+ }.AsQueryable();
+
+ // Act
+ Action action = () => queryable.Select(config, selector);
+
+ // Assert
+ action.Should().NotThrow();
+ }
+
+ [Theory(Skip = "873")]
+ [InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsProp[\"jwt\"]")]
+ [InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsField[\"jwt\"]")]
+ [InlineData("c => new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsProp[\"jwt\"]")]
+ [InlineData("c => new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsField[\"jwt\"]")]
+ public void UsingClassAsType_WhenAddedToDefaultDynamicLinqCustomTypeProvider_ShouldBeOk(string selector1, string selector2)
+ {
+ // Arrange
+ var config = new ParsingConfig();
+ config.UseDefaultDynamicLinqCustomTypeProvider([typeof(Helpers.Models.AppSettings), typeof(Helpers.Models.AppSettings3)]);
+
+ var queryable = new[]
+ {
+ new Message("Alice", "Bob")
+ }.AsQueryable();
+
+ // Act
+ Action action = () => queryable.Select(config, selector1).Select(config, selector2);
+
+ // Assert
+ action.Should().NotThrow();
+ }
+
+ [Theory]
+ [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings2.SettingsProp[\"jwt\"]")]
+ [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings2.SettingsField[\"jwt\"]")]
+ [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings2.SettingsProp[\"jwt\"]")]
+ [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings2.SettingsField[\"jwt\"]")]
+ public void UsingStaticClassWithDynamicTypeAttribute_ShouldBeOk(string selector)
+ {
+ // Arrange
+ var queryable = new[]
+ {
+ new Message("Alice", "Bob")
+ }.AsQueryable();
+
+ // Act
+ Action action = () => queryable.Select(selector);
+
+ // Assert
+ action.Should().NotThrow();
+ }
}
\ No newline at end of file
diff --git a/test/System.Linq.Dynamic.Core.Tests/TestClasses/TestCustomTypeProvider.cs b/test/System.Linq.Dynamic.Core.Tests/TestClasses/TestCustomTypeProvider.cs
index 5ae6565b2..ccb883c18 100644
--- a/test/System.Linq.Dynamic.Core.Tests/TestClasses/TestCustomTypeProvider.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/TestClasses/TestCustomTypeProvider.cs
@@ -9,6 +9,10 @@ public class TestCustomTypeProvider : AbstractDynamicLinqCustomTypeProvider, IDy
{
private HashSet? _customTypes;
+ public TestCustomTypeProvider() : base([])
+ {
+ }
+
public virtual HashSet GetCustomTypes()
{
if (_customTypes != null)
@@ -16,12 +20,13 @@ public virtual HashSet GetCustomTypes()
return _customTypes;
}
- _customTypes = new HashSet(FindTypesMarkedWithDynamicLinqTypeAttribute(new[] { GetType().GetTypeInfo().Assembly }))
+ _customTypes = new HashSet(FindTypesMarkedWithDynamicLinqTypeAttribute([GetType().GetTypeInfo().Assembly]))
{
typeof(CustomClassWithStaticMethod),
typeof(StaticHelper),
typeof(StaticHelper.Nested)
};
+
return _customTypes;
}