DynamicUtils
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace Newtonsoft.Json.Utilities
{
internal static class DynamicUtils
{
internal static class BinderWrapper
{
public const string CSharpAssemblyName = "Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private const string BinderTypeName = "Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private const string CSharpArgumentInfoTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private const string CSharpArgumentInfoFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private const string CSharpBinderFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private static object _getCSharpArgumentInfoArray;
private static object _setCSharpArgumentInfoArray;
private static MethodCall<object, object> _getMemberCall;
private static MethodCall<object, object> _setMemberCall;
private static bool _init;
private static void Init()
{
if (!_init) {
Type type = Type.GetType("Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", false);
if (type == (Type)null)
throw new InvalidOperationException("Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.".FormatWith(CultureInfo.InvariantCulture, "Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"));
int[] values = new int[1];
_getCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(values);
_setCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0, 3);
CreateMemberCalls();
_init = true;
}
}
private static object CreateSharpArgumentInfoArray(params int[] values)
{
Type type = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
Type type2 = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
Array array = Array.CreateInstance(type, values.Length);
for (int i = 0; i < values.Length; i++) {
MethodInfo method = type.GetMethod("Create", new Type[2] {
type2,
typeof(string)
});
object value = method.Invoke(null, new object[2] {
0,
null
});
array.SetValue(value, i);
}
return array;
}
private static void CreateMemberCalls()
{
Type type = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", true);
Type type2 = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", true);
Type type3 = Type.GetType("Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", true);
Type type4 = typeof(IEnumerable<>).MakeGenericType(type);
MethodInfo method = type3.GetMethod("GetMember", new Type[4] {
type2,
typeof(string),
typeof(Type),
type4
});
_getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(method);
MethodInfo method2 = type3.GetMethod("SetMember", new Type[4] {
type2,
typeof(string),
typeof(Type),
type4
});
_setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(method2);
}
public static CallSiteBinder GetMember(string name, Type context)
{
Init();
return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray);
}
public static CallSiteBinder SetMember(string name, Type context)
{
Init();
return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray);
}
}
public static IEnumerable<string> GetDynamicMemberNames(this IDynamicMetaObjectProvider dynamicProvider)
{
DynamicMetaObject metaObject = dynamicProvider.GetMetaObject(Expression.Constant(dynamicProvider));
return metaObject.GetDynamicMemberNames();
}
}
}