Skip to content

Commit

Permalink
Extract LateBinders
Browse files Browse the repository at this point in the history
  • Loading branch information
metoule committed Aug 18, 2024
1 parent 54a58ca commit 084e294
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 70 deletions.
70 changes: 0 additions & 70 deletions src/DynamicExpresso.Core/Parsing/Parser.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using DynamicExpresso.Exceptions;
using DynamicExpresso.Reflection;
Expand Down Expand Up @@ -2590,71 +2586,5 @@ private static Expression GenerateNullableTypeConversion(Expression expr)
var conversionType = typeof(Nullable<>).MakeGenericType(exprType);
return Expression.ConvertChecked(expr, conversionType);
}

/// <summary>
/// Binds to a member access of an instance as late as possible. This allows the use of anonymous types on dynamic values.
/// </summary>
private class LateGetMemberCallSiteBinder : CallSiteBinder
{
private readonly string _propertyOrFieldName;

public LateGetMemberCallSiteBinder(string propertyOrFieldName)
{
_propertyOrFieldName = propertyOrFieldName;
}

public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel)
{
var binder = Microsoft.CSharp.RuntimeBinder.Binder.GetMember(
Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None,
_propertyOrFieldName,
TypeUtils.RemoveArrayType(args[0]?.GetType()),
new[] { Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags.None, null) }
);
return binder.Bind(args, parameters, returnLabel);
}
}

/// <summary>
/// Binds to a method invocation of an instance as late as possible. This allows the use of anonymous types on dynamic values.
/// </summary>
private class LateInvokeMethodCallSiteBinder : CallSiteBinder
{
private readonly string _methodName;

public LateInvokeMethodCallSiteBinder(string methodName)
{
_methodName = methodName;
}

public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel)
{
var binderM = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None,
_methodName,
null,
TypeUtils.RemoveArrayType(args[0]?.GetType()),
parameters.Select(x => Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags.None, null))
);
return binderM.Bind(args, parameters, returnLabel);
}
}

/// <summary>
/// Binds to an items invocation of an instance as late as possible. This allows the use of anonymous types on dynamic values.
/// </summary>
private class LateInvokeIndexCallSiteBinder : CallSiteBinder
{
public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel)
{
var binder = Microsoft.CSharp.RuntimeBinder.Binder.GetIndex(
Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None,
TypeUtils.RemoveArrayType(args[0]?.GetType()),
parameters.Select(x => Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags.None, null))
);
return binder.Bind(args, parameters, returnLabel);
}
}

}
}
71 changes: 71 additions & 0 deletions src/DynamicExpresso.Core/Resolution/LateBinders.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using DynamicExpresso.Reflection;
using Microsoft.CSharp.RuntimeBinder;

namespace DynamicExpresso.Resolution
{
internal class LateGetMemberCallSiteBinder : CallSiteBinder
{
private readonly string _propertyOrFieldName;

public LateGetMemberCallSiteBinder(string propertyOrFieldName)
{
_propertyOrFieldName = propertyOrFieldName;
}

public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel)
{
var binder = Binder.GetMember(
CSharpBinderFlags.None,
_propertyOrFieldName,
TypeUtils.RemoveArrayType(args[0]?.GetType()),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }
);
return binder.Bind(args, parameters, returnLabel);
}
}

/// <summary>
/// Binds to a method invocation of an instance as late as possible. This allows the use of anonymous types on dynamic values.
/// </summary>
internal class LateInvokeMethodCallSiteBinder : CallSiteBinder
{
private readonly string _methodName;

public LateInvokeMethodCallSiteBinder(string methodName)
{
_methodName = methodName;
}

public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel)
{
var binderM = Binder.InvokeMember(
CSharpBinderFlags.None,
_methodName,
null,
TypeUtils.RemoveArrayType(args[0]?.GetType()),
parameters.Select(x => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null))
);
return binderM.Bind(args, parameters, returnLabel);
}
}

/// <summary>
/// Binds to an items invocation of an instance as late as possible. This allows the use of anonymous types on dynamic values.
/// </summary>
internal class LateInvokeIndexCallSiteBinder : CallSiteBinder
{
public override Expression Bind(object[] args, ReadOnlyCollection<ParameterExpression> parameters, LabelTarget returnLabel)
{
var binder = Binder.GetIndex(
CSharpBinderFlags.None,
TypeUtils.RemoveArrayType(args[0]?.GetType()),
parameters.Select(x => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null))
);
return binder.Bind(args, parameters, returnLabel);
}
}
}

0 comments on commit 084e294

Please sign in to comment.