Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions System.Linq.Dynamic.Core.sln
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ Project("{7CF6DF6D-3B04-46F8-A40B-537D21BCA0B4}") = "System.Linq.Dynamic.Core",
{D3804228-91F4-4502-9595-39584E510002} = {D3804228-91F4-4502-9595-39584E510002}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleAppPerformanceTest236", "src-console\ConsoleAppPerformanceTest236\ConsoleAppPerformanceTest236.csproj", "{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}"
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Expand Down Expand Up @@ -388,6 +393,22 @@ Global
{591F9224-A8D6-49CF-8AF8-F9B383C1F9FF}.Release|x64.Build.0 = Release|Any CPU
{591F9224-A8D6-49CF-8AF8-F9B383C1F9FF}.Release|x86.ActiveCfg = Release|Any CPU
{591F9224-A8D6-49CF-8AF8-F9B383C1F9FF}.Release|x86.Build.0 = Release|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Debug|ARM.ActiveCfg = Debug|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Debug|ARM.Build.0 = Debug|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Debug|x64.ActiveCfg = Debug|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Debug|x64.Build.0 = Debug|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Debug|x86.ActiveCfg = Debug|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Debug|x86.Build.0 = Debug|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Release|Any CPU.Build.0 = Release|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Release|ARM.ActiveCfg = Release|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Release|ARM.Build.0 = Release|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Release|x64.ActiveCfg = Release|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Release|x64.Build.0 = Release|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Release|x86.ActiveCfg = Release|Any CPU
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -412,6 +433,7 @@ Global
{F1880F07-238F-4A3A-9E58-141350665E1F} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62}
{926D446C-8358-465A-AFAC-2F9078C22262} = {ECA5702B-5D32-4888-A34E-9461FC533F23}
{591F9224-A8D6-49CF-8AF8-F9B383C1F9FF} = {1384C18E-DCF3-4A5B-9560-2BF5DD8C51CE}
{E9C52E5E-28DC-4D45-B9AB-1B2CF2924A84} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {94C56722-194E-4B8B-BC23-B3F754E89A20}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net472</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.7" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\System.Linq.Dynamic.Core\System.Linq.Dynamic.Core.csproj" />
</ItemGroup>

</Project>
11 changes: 11 additions & 0 deletions src-console/ConsoleAppPerformanceTest236/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ConsoleAppPerformanceTest236
{
class Program
{
static void Main(string[] args)
{
Test.DoIt();
int x = 0;
}
}
}
Binary file not shown.
24 changes: 24 additions & 0 deletions src-console/ConsoleAppPerformanceTest236/Test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Linq;
using System.Linq.Dynamic.Core;

namespace ConsoleAppPerformanceTest236
{
public static class Test
{
public static void DoIt()
{
var q = User.GenerateSampleModels(10000).AsQueryable();

int count = 100;
for (int i = 0; i <= count; i++)
{
if (i % 10 == 0)
{
Console.WriteLine(i);
}
var result = q.OrderBy("FullName ASC, City DESC").FirstOrDefault();
}
}
}
}
43 changes: 43 additions & 0 deletions src-console/ConsoleAppPerformanceTest236/User.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using RandomDataGenerator.FieldOptions;
using RandomDataGenerator.Randomizers;

namespace ConsoleAppPerformanceTest236
{
public class User
{
public Guid Id { get; set; }

public string FullName { get; set; }

public string City { get; set; }

public int? NullableInt { get; set; }

public int Income { get; set; }

public static IList<User> GenerateSampleModels(int total, bool allowNullableProfiles = false)
{
var list = new List<User>();

var randomizerFullName = RandomizerFactory.GetRandomizer(new FieldOptionsFullName());
var randomizerCity= RandomizerFactory.GetRandomizer(new FieldOptionsCity());

for (int i = 0; i < total; i++)
{
var user = new User
{
Id = Guid.NewGuid(),
FullName = randomizerFullName.Generate(),
City = randomizerCity.Generate(),
Income = 1 + i % 15 * 100
};

list.Add(user);
}

return list.ToArray();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Reflection;
using System.Linq.Dynamic.Core.Validation;
using System.Reflection;

namespace System.Linq.Dynamic.Core.CustomTypeProviders
{
/// <summary>
/// The abstract DynamicLinqCustomTypeProvider which is used by the <see cref="IDynamicLinkCustomTypeProvider"/> and can be used by a custom TypeProvider like in .NET Core.
/// The abstract DynamicLinqCustomTypeProvider which is used by the DefaultDynamicLinqCustomTypeProvider and can be used by a custom TypeProvider like in .NET Core.
/// </summary>
public abstract class AbstractDynamicLinqCustomTypeProvider
{
/// <summary>
/// Finds the types marked with DynamicLinqTypeAttribute.
/// Finds the unique types marked with DynamicLinqTypeAttribute.
/// </summary>
/// <param name="assemblies">The assemblies to process.</param>
/// <returns>IEnumerable{Type}</returns>
/// <returns><see cref="IEnumerable{Type}" /></returns>
protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute([NotNull] IEnumerable<Assembly> assemblies)
{
Check.NotNull(assemblies, nameof(assemblies));
#if !NET35
assemblies = assemblies.Where(x => !x.IsDynamic);
#endif
var definedTypes = GetAssemblyTypes(assemblies);

#if (WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
return definedTypes.Where(x => x.CustomAttributes.Any(y => y.AttributeType == typeof(DynamicLinqTypeAttribute))).Select(x => x.AsType());
#else
return definedTypes.Where(x => x.GetCustomAttributes(typeof(DynamicLinqTypeAttribute), false).Any());
assemblies = assemblies.Where(a => !a.IsDynamic);
#endif
return GetAssemblyTypesWithDynamicLinqTypeAttribute(assemblies).Distinct().ToArray();
}

/// <summary>
Expand All @@ -41,7 +35,7 @@ protected Type ResolveType([NotNull] IEnumerable<Assembly> assemblies, [NotNull]
Check.NotNull(assemblies, nameof(assemblies));
Check.NotEmpty(typeName, nameof(typeName));

foreach (Assembly assembly in assemblies)
foreach (var assembly in assemblies)
{
Type resolvedType = assembly.GetType(typeName, false, true);
if (resolvedType != null)
Expand All @@ -55,28 +49,32 @@ protected Type ResolveType([NotNull] IEnumerable<Assembly> assemblies, [NotNull]

#if (WINDOWS_APP || DOTNET5_1 || UAP10_0 || NETSTANDARD)
/// <summary>
/// Gets the assembly types in an Exception friendly way.
/// Gets the assembly types annotated with <see cref="DynamicLinqTypeAttribute"/> in an Exception friendly way.
/// </summary>
/// <param name="assemblies">The assemblies to process.</param>
/// <returns>IEnumerable{Type}</returns>
protected IEnumerable<TypeInfo> GetAssemblyTypes([NotNull] IEnumerable<Assembly> assemblies)
/// <returns><see cref="IEnumerable{Type}" /></returns>
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute([NotNull] IEnumerable<Assembly> assemblies)
{
Check.NotNull(assemblies, nameof(assemblies));

foreach (var assembly in assemblies)
{
IEnumerable<TypeInfo> definedTypes = null;
Type[] definedTypes = null;

try
{
definedTypes = assembly.DefinedTypes;
definedTypes = assembly.ExportedTypes.Where(t => t.GetTypeInfo().IsDefined(typeof(DynamicLinqTypeAttribute), false)).ToArray();
}
catch (ReflectionTypeLoadException reflectionTypeLoadException)
{
definedTypes = reflectionTypeLoadException.Types;
}
catch
{
// Ignore error
// Ignore all other exceptions
}

if (definedTypes != null)
if (definedTypes != null && definedTypes.Length > 0)
{
foreach (var definedType in definedTypes)
{
Expand All @@ -87,28 +85,33 @@ protected IEnumerable<TypeInfo> GetAssemblyTypes([NotNull] IEnumerable<Assembly>
}
#else
/// <summary>
/// Gets the assembly types in an Exception friendly way.
/// Gets the assembly types annotated with <see cref="DynamicLinqTypeAttribute"/> in an Exception friendly way.
/// </summary>
/// <param name="assemblies">The assemblies to process.</param>
/// <returns>IEnumerable{Type}</returns>
protected IEnumerable<Type> GetAssemblyTypes([NotNull] IEnumerable<Assembly> assemblies)
/// <returns><see cref="IEnumerable{Type}" /></returns>
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute([NotNull] IEnumerable<Assembly> assemblies)
{
Check.NotNull(assemblies, nameof(assemblies));

foreach (var assembly in assemblies)
foreach (var assembly in assemblies.Where(a => !a.GlobalAssemblyCache)) // Skip System DLL's
{
IEnumerable<Type> definedTypes = null;
Type[] definedTypes = null;

try
{
definedTypes = assembly.GetTypes();
definedTypes = assembly.GetExportedTypes()
.Where(t => t.IsDefined(typeof(DynamicLinqTypeAttribute), false)).ToArray();
}
catch (ReflectionTypeLoadException reflectionTypeLoadException)
{
definedTypes = reflectionTypeLoadException.Types;
}
catch
{
// Ignore error
// Ignore all other exceptions
}

if (definedTypes != null)
if (definedTypes != null && definedTypes.Length > 0)
{
foreach (var definedType in definedTypes)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#if !(WINDOWS_APP || UAP10_0)
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq.Dynamic.Core.Validation;
using System.Reflection;

namespace System.Linq.Dynamic.Core.CustomTypeProviders
{
/// <summary>
/// The default <see cref="IDynamicLinkCustomTypeProvider"/>.
/// The default implementation for <see cref="IDynamicLinkCustomTypeProvider"/>.
///
/// Scans the current AppDomain for all types marked with <see cref="DynamicLinqTypeAttribute"/>, and adds them as custom Dynamic Link types.
///
/// Also provides functionality to resolve a Type in the current Application Domain.
Expand All @@ -16,12 +16,33 @@ namespace System.Linq.Dynamic.Core.CustomTypeProviders
public class DefaultDynamicLinqCustomTypeProvider : AbstractDynamicLinqCustomTypeProvider, IDynamicLinkCustomTypeProvider
{
private readonly IAssemblyHelper _assemblyHelper = new DefaultAssemblyHelper();
private readonly bool _cacheCustomTypes;

private HashSet<Type> _cachedCustomTypes;

/// <summary>
/// Initializes a new instance of the <see cref="DefaultDynamicLinqCustomTypeProvider"/> class.
/// </summary>
/// <param name="cacheCustomTypes">Defines whether to cache the CustomTypes which are found in the Application Domain. Default set to 'true'.</param>
public DefaultDynamicLinqCustomTypeProvider(bool cacheCustomTypes = true)
{
_cacheCustomTypes = cacheCustomTypes;
}

/// <inheritdoc cref="IDynamicLinkCustomTypeProvider.GetCustomTypes"/>
public virtual HashSet<Type> GetCustomTypes()
{
IEnumerable<Assembly> assemblies = _assemblyHelper.GetAssemblies();
return new HashSet<Type>(FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies));
if (_cacheCustomTypes)
{
if (_cachedCustomTypes == null)
{
_cachedCustomTypes = GetCustomTypesInternal();
}

return _cachedCustomTypes;
}

return GetCustomTypesInternal();
}

/// <inheritdoc cref="IDynamicLinkCustomTypeProvider.ResolveType"/>
Expand All @@ -32,6 +53,11 @@ public Type ResolveType(string typeName)
IEnumerable<Assembly> assemblies = _assemblyHelper.GetAssemblies();
return ResolveType(assemblies, typeName);
}

private HashSet<Type> GetCustomTypesInternal()
{
IEnumerable<Assembly> assemblies = _assemblyHelper.GetAssemblies();
return new HashSet<Type>(FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies));
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using JetBrains.Annotations;
using System.Collections.Generic;

namespace System.Linq.Dynamic.Core.CustomTypeProviders
{
Expand All @@ -11,7 +11,7 @@ public interface IDynamicLinkCustomTypeProvider
/// <summary>
/// Returns a list of custom types that System.Linq.Dynamic.Core will understand.
/// </summary>
/// <returns>A <see cref="HashSet&lt;Type&gt;" /> list of custom types.</returns>
/// <returns>A <see cref="HashSet{Type}" /> list of custom types.</returns>
HashSet<Type> GetCustomTypes();

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1564,7 +1564,7 @@ Type FindType(string name)
{
_keywordsHelper.TryGetValue(name, out object type);

var result = type as Type;
Type result = type as Type;
if (result != null)
{
return result;
Expand All @@ -1584,6 +1584,7 @@ Type FindType(string name)
{
return _root.Type;
}

if (_it != null && _it.Type.Namespace + "." + _it.Type.Name == name)
{
return _it.Type;
Expand Down
2 changes: 1 addition & 1 deletion src/System.Linq.Dynamic.Core/ParsingConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public IDynamicLinkCustomTypeProvider CustomTypeProvider
get
{
#if !(DOTNET5_1 || WINDOWS_APP || UAP10_0 || NETSTANDARD)
// only use DefaultDynamicLinqCustomTypeProvider if not WINDOWS_APP || UAP10_0 || NETSTANDARD
// only use DefaultDynamicLinqCustomTypeProvider for full .NET Framework
return _customTypeProvider ?? (_customTypeProvider = new DefaultDynamicLinqCustomTypeProvider());
#else
return _customTypeProvider;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@
<Reference Include="Moq, Version=4.10.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\..\packages\Moq.4.10.0\lib\net45\Moq.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NFluent, Version=2.1.1.107, Culture=neutral, PublicKeyToken=18828b37b84b1437, processorArchitecture=MSIL">
<HintPath>..\..\packages\NFluent.2.1.1\lib\net45\NFluent.dll</HintPath>
Expand Down
Loading