Информация об изменениях

Сообщение Re[10]: Приоритет вызова перегруженных методов от 06.07.2016 11:45

Изменено 06.07.2016 13:55 Serginio1

Здравствуйте, Sinix, Вы писали:

Для Динамиков нашел решение
https://gist.github.com/jflam/777574
https://github.com/mgravell/fast-member/blob/master/FastMember/CallSiteCache.cs

На основании сделал для разного рода DynamicObject


public class DynamicInvoker
    {
       public static object InvokeMember(object target, string methodName, params object[] args)
        {
            var targetParam = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
            CSharpArgumentInfo[] parameterFlags = new CSharpArgumentInfo[args.Length + 1];
            System.Linq.Expressions.Expression[] parameters = new System.Linq.Expressions.Expression[args.Length + 1];
            parameterFlags[0] = targetParam;
            parameters[0] = System.Linq.Expressions.Expression.Constant(target);
            for (int i = 0; i < args.Length; i++)
            {
                parameterFlags[i + 1] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null);
                parameters[i + 1] = System.Linq.Expressions.Expression.Constant(args[i]);
            }
            var csb = Binder.InvokeMember(CSharpBinderFlags.None, methodName, null, typeof(DynamicInvoker), parameterFlags);
            var de = System.Linq.Expressions.Expression.Dynamic(csb, typeof(object), parameters);
            LambdaExpression expr = System.Linq.Expressions.Expression.Lambda(de);
            return expr.Compile().DynamicInvoke();
        }

        public static object GetValue(object target,string name)
        {
            
            CallSite<Func<CallSite, object, object>> callSite = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, name, typeof(DynamicInvoker), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
               
            return callSite.Target(callSite, target);
        }
        public static void SetValue(object target, string name,  object value)
        {
          
                CallSite<Func<CallSite, object, object, object>> callSite = CallSite<Func<CallSite, object, object, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, name, typeof(DynamicInvoker), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
                callSite.Target(callSite, target, value);
        }


    }



И вызов


void ВывестиСвойство(object target, string ИмяСвойства)
        {
            textBox.AppendText(ИмяСвойства+"="+DynamicInvoker.GetValue(target, ИмяСвойства).ToString() + Environment.NewLine);

        }
        private void button_Click(object sender, RoutedEventArgs e)
        {
            dynamic res = new ExpandoObject();
            res.Имя = "Тест ExpandoObject";
            res.Число = 456;
            res.ВСтроку = (Func<string>)(() => res.Имя);
            res.Сумма = (Func<int,int,int>)((x,y) => x+y);

            textBox.Clear();
            textBox.AppendText("ВСтроку="+DynamicInvoker.InvokeMember(res, "ВСтроку").ToString()+Environment.NewLine);
            textBox.AppendText("Сумма=" + DynamicInvoker.InvokeMember(res, "Сумма", 1, 2).ToString() + Environment.NewLine);

            ВывестиСвойство(res, "Имя");
            ВывестиСвойство(res, "Число");

            DynamicInvoker.SetValue(res, "Имя","Новое Имя");
            DynamicInvoker.SetValue(res, "Число","768");

            ВывестиСвойство(res, "Имя");
            ВывестиСвойство(res, "Число");

        }
Re[10]: Приоритет вызова перегруженных методов
Здравствуйте, Sinix, Вы писали:

Для Динамиков нашел решение
https://gist.github.com/jflam/777574
https://github.com/mgravell/fast-member/blob/master/FastMember/CallSiteCache.cs

На основании сделал для разного рода DynamicObject


using System.Text;
using System.Threading.Tasks;
using System.Linq.Expressions;
using Microsoft.CSharp.RuntimeBinder;
using System.Dynamic;
using System.Runtime.CompilerServices;
namespace Тестовый
{
   public class DynamicInvoker
    {
       public static object InvokeMember(object target, string methodName, params object[] args)
        {
            var targetParam = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
            CSharpArgumentInfo[] parameterFlags = new CSharpArgumentInfo[args.Length + 1];
            System.Linq.Expressions.Expression[] parameters = new System.Linq.Expressions.Expression[args.Length + 1];
            parameterFlags[0] = targetParam;
            parameters[0] = System.Linq.Expressions.Expression.Constant(target);
            for (int i = 0; i < args.Length; i++)
            {
                parameterFlags[i + 1] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null);
                parameters[i + 1] = System.Linq.Expressions.Expression.Constant(args[i]);
            }
            var csb = Binder.InvokeMember(CSharpBinderFlags.None, methodName, null, typeof(DynamicInvoker), parameterFlags);
            var de = DynamicExpression.Dynamic(csb, typeof(object), parameters);
            LambdaExpression expr = System.Linq.Expressions.Expression.Lambda(de);
            return expr.Compile().DynamicInvoke();
        }

        public static object GetValue(object target,string name)
        {
            
            CallSite<Func<CallSite, object, object>> callSite = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, name, typeof(DynamicInvoker), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
               
            return callSite.Target(callSite, target);
        }
        public static void SetValue(object target, string name,  object value)
        {
          
                CallSite<Func<CallSite, object, object, object>> callSite = CallSite<Func<CallSite, object, object, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, name, typeof(DynamicInvoker), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
                callSite.Target(callSite, target, value);
        }


    }
}



И вызов


void ВывестиСвойство(object target, string ИмяСвойства)
        {
            textBox.AppendText(ИмяСвойства+"="+DynamicInvoker.GetValue(target, ИмяСвойства).ToString() + Environment.NewLine);

        }
        private void button_Click(object sender, RoutedEventArgs e)
        {
            dynamic res = new ExpandoObject();
            res.Имя = "Тест ExpandoObject";
            res.Число = 456;
            res.ВСтроку = (Func<string>)(() => res.Имя);
            res.Сумма = (Func<int,int,int>)((x,y) => x+y);

            textBox.Clear();
            textBox.AppendText("ВСтроку="+DynamicInvoker.InvokeMember(res, "ВСтроку").ToString()+Environment.NewLine);
            textBox.AppendText("Сумма=" + DynamicInvoker.InvokeMember(res, "Сумма", 1, 2).ToString() + Environment.NewLine);

            ВывестиСвойство(res, "Имя");
            ВывестиСвойство(res, "Число");

            DynamicInvoker.SetValue(res, "Имя","Новое Имя");
            DynamicInvoker.SetValue(res, "Число","768");

            ВывестиСвойство(res, "Имя");
            ВывестиСвойство(res, "Число");

        }