using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleTest
{
class Program
{
static void Main(string[] args)
{
var a = new A { Prop1 = 0, Prop2 = "1", Prop3 = 2.0 };
Console.WriteLine(a);
dynamic d = new Decorator<A>(a);
d.Prop1 = 3;
d.Prop2 = "4";
d.Prop3 = 5.0;
Console.WriteLine(a);
Console.ReadKey();
}
}
class A
{
public int Prop1 { get; set; }
public string Prop2 { get; set; }
public double Prop3 { get; set; }
public override string ToString() => $"Prop1={Prop1}, Prop1={Prop2}, Prop1={Prop3}";
}
class Decorator<T> : DynamicObject
{
private static readonly IReadOnlyDictionary<string, Action<T, object>> props;
static Decorator()
{
props = typeof(T).GetProperties().ToDictionary(pi => pi.Name, CreateSetter);
}
private static Action<T, object> CreateSetter(PropertyInfo pi)
{
var obj = Expression.Parameter(typeof(T), "t");
var val = Expression.Parameter(typeof(object), "o");
var prop = Expression.Property(obj, pi);
var set = Expression.Assign(prop, Expression.Convert(val, pi.PropertyType));
var lambda = Expression.Lambda<Action<T, object>>(set, obj, val);
return lambda.Compile();
}
private readonly T obj;
public Decorator(T obj)
{
this.obj = obj;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
Action<T, object> setter;
if (!props.TryGetValue(binder.Name, out setter)) return false;
Console.WriteLine($"{binder.Name} = {value}");
setter(obj, value);
return true;
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYzsKdXNpbmcgU3lzdGVtLkR5bmFtaWM7CnVzaW5nIFN5c3RlbS5MaW5xOwp1c2luZyBTeXN0ZW0uTGlucS5FeHByZXNzaW9uczsKdXNpbmcgU3lzdGVtLlJlZmxlY3Rpb247CgpuYW1lc3BhY2UgQ29uc29sZVRlc3QKewogICAgY2xhc3MgUHJvZ3JhbQogICAgewogICAgICAgIHN0YXRpYyB2b2lkIE1haW4oc3RyaW5nW10gYXJncykKICAgICAgICB7CiAgICAgICAgICAgIHZhciBhID0gbmV3IEEgeyBQcm9wMSA9IDAsIFByb3AyID0gIjEiLCBQcm9wMyA9IDIuMCB9OwogICAgICAgICAgICBDb25zb2xlLldyaXRlTGluZShhKTsKICAgICAgICAgICAgZHluYW1pYyBkID0gbmV3IERlY29yYXRvcjxBPihhKTsKICAgICAgICAgICAgZC5Qcm9wMSA9IDM7CiAgICAgICAgICAgIGQuUHJvcDIgPSAiNCI7CiAgICAgICAgICAgIGQuUHJvcDMgPSA1LjA7CiAgICAgICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKGEpOwogICAgICAgICAgICBDb25zb2xlLlJlYWRLZXkoKTsKICAgICAgICB9CiAgICB9CgogICAgY2xhc3MgQQogICAgewogICAgICAgIHB1YmxpYyBpbnQgUHJvcDEgeyBnZXQ7IHNldDsgfQogICAgICAgIHB1YmxpYyBzdHJpbmcgUHJvcDIgeyBnZXQ7IHNldDsgfQogICAgICAgIHB1YmxpYyBkb3VibGUgUHJvcDMgeyBnZXQ7IHNldDsgfQogICAgICAgIHB1YmxpYyBvdmVycmlkZSBzdHJpbmcgVG9TdHJpbmcoKSA9PiAkIlByb3AxPXtQcm9wMX0sIFByb3AxPXtQcm9wMn0sIFByb3AxPXtQcm9wM30iOwogICAgfQoKICAgIGNsYXNzIERlY29yYXRvcjxUPiA6IER5bmFtaWNPYmplY3QKICAgIHsKICAgICAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBJUmVhZE9ubHlEaWN0aW9uYXJ5PHN0cmluZywgQWN0aW9uPFQsIG9iamVjdD4+IHByb3BzOwoKICAgICAgICBzdGF0aWMgRGVjb3JhdG9yKCkKICAgICAgICB7CiAgICAgICAgICAgIHByb3BzID0gdHlwZW9mKFQpLkdldFByb3BlcnRpZXMoKS5Ub0RpY3Rpb25hcnkocGkgPT4gcGkuTmFtZSwgQ3JlYXRlU2V0dGVyKTsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgc3RhdGljIEFjdGlvbjxULCBvYmplY3Q+IENyZWF0ZVNldHRlcihQcm9wZXJ0eUluZm8gcGkpCiAgICAgICAgewogICAgICAgICAgICB2YXIgb2JqID0gRXhwcmVzc2lvbi5QYXJhbWV0ZXIodHlwZW9mKFQpLCAidCIpOwogICAgICAgICAgICB2YXIgdmFsID0gRXhwcmVzc2lvbi5QYXJhbWV0ZXIodHlwZW9mKG9iamVjdCksICJvIik7CiAgICAgICAgICAgIHZhciBwcm9wID0gRXhwcmVzc2lvbi5Qcm9wZXJ0eShvYmosIHBpKTsKICAgICAgICAgICAgdmFyIHNldCA9IEV4cHJlc3Npb24uQXNzaWduKHByb3AsIEV4cHJlc3Npb24uQ29udmVydCh2YWwsIHBpLlByb3BlcnR5VHlwZSkpOwogICAgICAgICAgICB2YXIgbGFtYmRhID0gRXhwcmVzc2lvbi5MYW1iZGE8QWN0aW9uPFQsIG9iamVjdD4+KHNldCwgb2JqLCB2YWwpOwogICAgICAgICAgICByZXR1cm4gbGFtYmRhLkNvbXBpbGUoKTsKICAgICAgICB9CgogICAgICAgIHByaXZhdGUgcmVhZG9ubHkgVCBvYmo7CgogICAgICAgIHB1YmxpYyBEZWNvcmF0b3IoVCBvYmopCiAgICAgICAgewogICAgICAgICAgICB0aGlzLm9iaiA9IG9iajsKICAgICAgICB9CgogICAgICAgIHB1YmxpYyBvdmVycmlkZSBib29sIFRyeVNldE1lbWJlcihTZXRNZW1iZXJCaW5kZXIgYmluZGVyLCBvYmplY3QgdmFsdWUpCiAgICAgICAgewogICAgICAgICAgICBBY3Rpb248VCwgb2JqZWN0PiBzZXR0ZXI7CiAgICAgICAgICAgIGlmICghcHJvcHMuVHJ5R2V0VmFsdWUoYmluZGVyLk5hbWUsIG91dCBzZXR0ZXIpKSByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCQie2JpbmRlci5OYW1lfSA9IHt2YWx1ZX0iKTsKICAgICAgICAgICAgc2V0dGVyKG9iaiwgdmFsdWUpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICB9Cn0=