I was looking for a long time how to call ExpandoObject methods or DynamicObject heirs through reflection. On the Internet I found the library Dynamitey . But it does not work with .Net Core

Closed due to the fact that the essence of the question is not clear to the party PashaPash 14 Jul '16 at 14:34 .

Try to write more detailed questions. To get an answer, explain what exactly you see the problem, how to reproduce it, what you want to get as a result, etc. Give an example that clearly demonstrates the problem. If the question can be reformulated according to the rules set out in the certificate , edit it .

  • Why do you need reflection? Why not just say it in IDictionary<string, object> ? - VladD
  • Here is an official example (find Enumerating and Deleting Members ). - VladD
  • IDynamicMetaObjectProvider not only implements ExpandoObject. DynamicObject, JObject too. - Serginio
  • And I have IDictionary <string, object> implemented via IReflect. But you can't turn to DynamicObject there, JObject - Serginio
  • one
    @Serginio is good and welcome, but you should describe what solution you were looking for. Those. Your solution is too complicated for ExpandoObject. For the full implementation of IReflect, there is also a simpler solution. Those. You brought a solution, but you didn’t give a specific problem that you are trying to solve (that is, the problem is that you have a custom and incomplete implementation of IReflect, which for some reason you work with through IDynamicMetaObjectProvider). Suddenly there are simpler solutions for it. - PashaPash

2 answers 2

I was looking for a solution for Speakers for a long time (IDynamicMetaObjectProvider) found the solution https://gist.github.com/jflam/777574 https://github.com/mgravell/fast-member/blob/master/FastMember/CallSiteCache.cs

Based on made for all sorts of 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); } } } 

And challenge

 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, "Число"); } 

Checked on .Net Core. Works. Soon I will lay out the component with the support of objects supporting IDynamicMetaObjectProvider

    You can also use the heir DynamicObject

      class TestDynamicObject : DynamicObject { public override bool TrySetMember(SetMemberBinder binder, object value) { return true; } // получение свойства public override bool TryGetMember(GetMemberBinder binder, out object result) { result = binder.Name; return true; } // вызов метода public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { var res = new StringBuilder("{0}("); var param = new object[args.Length + 1]; param[0] = binder.Name; if (args.Length > 0) { Array.Copy(args, 0, param, 1, args.Length); for (int i = 0; i < args.Length; i++) { res.AppendFormat("{{{0}}},", i + 1); } res.Remove(res.Length - 1, 1); } res.Append(")"); result = String.Format(res.ToString(), param); return true; } 

    And an example of a call for example from 1C

     Тестовый=ъТип("TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); Тест=ъ(Врап.Новый(Тестовый.ПолучитьСсылку()," Свойство из Конструктора")); // Это аналог структуры, но с поддержкой методов РасширяемыйОбъект=ъ(Тест.ПолучитьExpandoObject()); Сообщить("ВСтроку="+РасширяемыйОбъект.ВСтроку()); Сообщить("Сумма=" + РасширяемыйОбъект.Сумма(1, 2)); Сообщить(РасширяемыйОбъект.Имя); Сообщить(РасширяемыйОбъект.Число); РасширяемыйОбъект.Имя="Новое Имя"; РасширяемыйОбъект.Число=768; // Добавим новое свойство РасширяемыйОбъект.НовоеСвойство="Новое Свойство"; Сообщить(РасширяемыйОбъект.Имя); Сообщить(РасширяемыйОбъект.Число); Сообщить(РасширяемыйОбъект.НовоеСвойство); НовыйРеквизит=ъ(Врап.Новый("System.Dynamic.ExpandoObject, System.Dynamic.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")); НовыйРеквизит.Имя="Новый Реквизит"; НовыйРеквизит.Значение=123; РасширяемыйОбъект.НовыйРквизит=НовыйРеквизит.ПолучитьСсылку(); Сообщить(ъ(РасширяемыйОбъект.НовыйРквизит).Имя); TestDynamicObject=ъТип("TestDllForCoreClr.TestDynamicObject, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); ДинамикОбъект=ъНовый(TestDynamicObject.ПолучитьСсылку()); ДинамикОбъект.УстановимЛюбоеСвойство="Чего то там"; Сообщить( ДинамикОбъект.ПолучитТоЧтоПередали); Сообщить(ДинамикОбъект.ПолучитТоЧтоПередалиСПараметрами(1,3.45,ТекущаяДата())); Сообщить(ДинамикОбъект.Ъ(1,3.45,ТекущаяДата())); Сообщить(Тест.ПолучитьАтрибутыПараметра()); Сообщить(Тест.СравнитьАтрибуты()); // product=ъНовый("Newtonsoft.Json.Linq.JObject, Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"); product=ъНовый("Newtonsoft.Json.Linq.JObject, Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"); product.ProductName = "Elbow Grease"; product.Enabled = true; product.Price = 4.90; product.StockCount = 9000; product.StockValue = 44100; DecompressionMethods= ъТип("System.Net.DecompressionMethods, System.Net.Primitives, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); // 'System.Runtime.Serialization.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' JArray=ъТип("Newtonsoft.Json.Linq.JArray, Newtonsoft.Json, Version=4.0.11.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed"); массив=ъ(Врап.Новый(JArray.ПолучитьСсылку(),"Real","OnSale")); product.Tags =массив.ПолучитьСсылку(); Сообщить(product.ToString()); 

    Unfortunately, Newtonsoft.Json for .Net Core does not work ToString () because it uses the System.Runtime.Serialization.Primitives library which in .Net Core is not