fork download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Dynamic;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using System.Reflection;
  7.  
  8. namespace ConsoleTest
  9. {
  10. class Program
  11. {
  12. static void Main(string[] args)
  13. {
  14. var a = new A { Prop1 = 0, Prop2 = "1", Prop3 = 2.0 };
  15. Console.WriteLine(a);
  16. dynamic d = new Decorator<A>(a);
  17. d.Prop1 = 3;
  18. d.Prop2 = "4";
  19. d.Prop3 = 5.0;
  20. Console.WriteLine(a);
  21. Console.ReadKey();
  22. }
  23. }
  24.  
  25. class A
  26. {
  27. public int Prop1 { get; set; }
  28. public string Prop2 { get; set; }
  29. public double Prop3 { get; set; }
  30. public override string ToString() => $"Prop1={Prop1}, Prop1={Prop2}, Prop1={Prop3}";
  31. }
  32.  
  33. class Decorator<T> : DynamicObject
  34. {
  35. private static readonly IReadOnlyDictionary<string, Action<T, object>> props;
  36.  
  37. static Decorator()
  38. {
  39. props = typeof(T).GetProperties().ToDictionary(pi => pi.Name, CreateSetter);
  40. }
  41.  
  42. private static Action<T, object> CreateSetter(PropertyInfo pi)
  43. {
  44. var obj = Expression.Parameter(typeof(T), "t");
  45. var val = Expression.Parameter(typeof(object), "o");
  46. var prop = Expression.Property(obj, pi);
  47. var set = Expression.Assign(prop, Expression.Convert(val, pi.PropertyType));
  48. var lambda = Expression.Lambda<Action<T, object>>(set, obj, val);
  49. return lambda.Compile();
  50. }
  51.  
  52. private readonly T obj;
  53.  
  54. public Decorator(T obj)
  55. {
  56. this.obj = obj;
  57. }
  58.  
  59. public override bool TrySetMember(SetMemberBinder binder, object value)
  60. {
  61. Action<T, object> setter;
  62. if (!props.TryGetValue(binder.Name, out setter)) return false;
  63. Console.WriteLine($"{binder.Name} = {value}");
  64. setter(obj, value);
  65. return true;
  66. }
  67. }
  68. }
Success #stdin #stdout 0.16s 141952KB
stdin
Standard input is empty
stdout
Prop1=0, Prop1=1, Prop1=2
Prop1 = 3
Prop2 = 4
Prop3 = 5
Prop1=3, Prop1=4, Prop1=5