Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Update PredefinedMethodsHelper
  • Loading branch information
StefH authored Jan 29, 2025
commit c25c3a3b69e4904437643361b57665923c4d9f5c
2 changes: 1 addition & 1 deletion src/System.Linq.Dynamic.Core/DynamicClassFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ private static Type EmitType(IList<DynamicProperty> properties, bool createParam
ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
ilgeneratorToString.Emit(OpCodes.Pop);
ilgeneratorToString.Emit(OpCodes.Ldloc_0);
ilgeneratorToString.Emit(OpCodes.Callvirt, PredefinedMethodsHelper.ObjectToString);
ilgeneratorToString.Emit(OpCodes.Callvirt, PredefinedMethodsHelper.ObjectInstanceToString);
ilgeneratorToString.Emit(OpCodes.Ret);

EmitEqualityOperators(typeBuilder, equals);
Expand Down
80 changes: 66 additions & 14 deletions src/System.Linq.Dynamic.Core/Parser/PredefinedMethodsHelper.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,82 @@
using System.Collections.Generic;
using System.Linq.Dynamic.Core.Validation;
using System.Reflection;

namespace System.Linq.Dynamic.Core.Parser;

internal static class PredefinedMethodsHelper
internal class PredefinedMethodsHelper
{
internal static readonly MethodInfo ObjectToString = typeof(object).GetMethod(nameof(ToString), BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null)!;
internal static readonly MethodInfo ObjectInstanceEquals = typeof(object).GetMethod(nameof(Equals), BindingFlags.Instance | BindingFlags.Public, null, [typeof(object)], null)!;
private static readonly BindingFlags _bindingFlags = BindingFlags.Public | BindingFlags.Instance;

internal static readonly MethodInfo ObjectInstanceToString = typeof(object).GetMethod(nameof(ToString), _bindingFlags, null, Type.EmptyTypes, null)!;
internal static readonly MethodInfo ObjectInstanceEquals = typeof(object).GetMethod(nameof(Equals), _bindingFlags, null, [typeof(object)], null)!;
internal static readonly MethodInfo ObjectStaticEquals = typeof(object).GetMethod(nameof(Equals), BindingFlags.Static | BindingFlags.Public, null, [typeof(object), typeof(object)], null)!;
internal static readonly MethodInfo ObjectStaticReferenceEquals = typeof(object).GetMethod(nameof(ReferenceEquals), BindingFlags.Static | BindingFlags.Public, null, [typeof(object), typeof(object)], null)!;

private readonly Dictionary<Type, HashSet<MethodInfo>> _supported = new()
{
{ typeof(bool), new HashSet<MethodInfo>() },
{ typeof(char), new HashSet<MethodInfo>() },
{ typeof(string), new HashSet<MethodInfo>() },
{ typeof(sbyte), new HashSet<MethodInfo>() },
{ typeof(byte), new HashSet<MethodInfo>() },
{ typeof(short), new HashSet<MethodInfo>() },
{ typeof(ushort), new HashSet<MethodInfo>() },
{ typeof(int), new HashSet<MethodInfo>() },
{ typeof(uint), new HashSet<MethodInfo>() },
{ typeof(long), new HashSet<MethodInfo>() },
{ typeof(ulong), new HashSet<MethodInfo>() },
{ typeof(float), new HashSet<MethodInfo>() },
{ typeof(double), new HashSet<MethodInfo>() },
{ typeof(decimal), new HashSet<MethodInfo>() },
// { typeof(DateTime), new HashSet<MethodInfo>() },
// { typeof(DateTimeOffset), new HashSet<MethodInfo>() },
// { typeof(TimeSpan), new HashSet<MethodInfo>() },
// { typeof(Guid), new HashSet<MethodInfo>() },
// { typeof(Uri), new HashSet<MethodInfo>() },
// { typeof(Enum), new HashSet<MethodInfo>() },
#if NET6_0_OR_GREATER
// { typeof(DateOnly), new HashSet<MethodInfo>() },
// { typeof(TimeOnly), new HashSet<MethodInfo>() },
#endif
};

public PredefinedMethodsHelper(ParsingConfig config)
{
foreach (var kvp in _supported)
{
Add(kvp.Key.GetMethod(nameof(Equals), _bindingFlags, null, [kvp.Key], null));
Add(kvp.Key.GetMethod(nameof(Equals), _bindingFlags, null, [typeof(object)], null));

Add(kvp.Key.GetMethod(nameof(ToString), _bindingFlags, null, Type.EmptyTypes, null));
Add(kvp.Key.GetMethod(nameof(ToString), _bindingFlags, null, [typeof(string)], null));
Add(kvp.Key.GetMethod(nameof(ToString), _bindingFlags, null, [typeof(IFormatProvider)], null));
Add(kvp.Key.GetMethod(nameof(ToString), _bindingFlags, null, [typeof(string), typeof(IFormatProvider)], null));
}

private static readonly HashSet<MemberInfo> ObjectToStringAndObjectEquals =
[
ObjectToString,
ObjectInstanceEquals,
ObjectStaticEquals,
ObjectStaticReferenceEquals
];
if (config.AllowEqualsAndToStringMethodsOnObject)
{
_supported[typeof(object)] = [ObjectInstanceToString, ObjectInstanceEquals, ObjectStaticEquals, ObjectStaticReferenceEquals];
Comment thread
StefH marked this conversation as resolved.
}
}

public static bool IsPredefinedMethod(ParsingConfig config, MemberInfo member)
public bool IsPredefinedMethod(Type type, MemberInfo member)
{
Check.NotNull(config);
Check.NotNull(type);
Check.NotNull(member);

return config.AllowEqualsAndToStringMethodsOnObject && ObjectToStringAndObjectEquals.Contains(member);
if (!_supported.TryGetValue(type, out var supported) || supported.Count == 0)
{
return false;
}

return supported.Contains(member);
}

private void Add(Type type, MethodInfo? method)
{
if (method != null)
{
_supported[type].Add(method);
}
}
}