c# - Duck Typing DynamicObject derivate -


i wrote class allows derivate specify of properties can lazy loaded. code is:

public abstract class selfhydratingentity<t> : dynamicobject t : class {     private readonly dictionary<string, loadablebackingfield> fields;      public selfhydratingentity(t original) {         this.original = original;         this.fields = this.getbackingfields().todictionary(f => f.name);     }      public t original { get; private set; }      protected virtual ienumerable<loadablebackingfield> getbackingfields() {         yield break;     }      public override bool trygetmember(getmemberbinder binder, out object result) {         loadablebackingfield field;         if (this.fields.trygetvalue(binder.name, out field)) {             result = field.getvalue();             return true;         } else {             var getter = propertyaccessor.getgetter(this.original.gettype(), binder.name);             result = getter(this.original);             return true;         }     }      public override bool trysetmember(setmemberbinder binder, object value) {         loadablebackingfield field;         if (this.fields.trygetvalue(binder.name, out field)) {             field.setvalue(value);             return true;         } else {             var setter = propertyaccessor.getsetter(this.original.gettype(), binder.name);             setter(this.original, value);             return true;         }     } } 

and derivate class:

public class selfhydratingperson : selfhydratingentity<iperson> {     private readonly idatarepository datarepository;      public selfhydratingderivate(idatarepository datarepository, iperson person)         : base(person) {         this.datarepository = datarepository     }      protected override ienumerable<loadablebackingfield> getbackingfields() {         yield return new loadablebackingfield("address", () => this.datarepository.addresses.get(this.original.addressid));     } } 

this works fine getting , settings property values, either runtimebinderexception when implicitly cast or invalidcastexception explicitly cast selfhydratingentity t.

i know can override dynamicobject.tryconvert method, i'm wondering what put in method. i've read lot duck typing today, , have tried out several libraries, none of them work particular scenario. of libraries i've tried today generate wrapper class using reflection.emit makes calls "get_" , "set_" methods , naturally use reflection find these methods on wrapped instance. selfhydratingentity of course doesn't have "get_" , "set_" methods defined.

so, i'm wondering if kind of thing possible. there way cast instance of selfhydratingentity t? i'm looking this:

var original = getoriginalperson(); dynamic person = new selfhydratingperson(new datarepository(), original);  string name = person.name;    // gets property value on original var address = person.address; // gets property value using loadablebackingfield registration  var iperson = (iperson)person; - or - var iperson = ducktype.as<iperson>(person); 

have seen duck typing project. looks pretty good. have found great example mauricio. uses windsor castle dynamic proxy intercept method calls

using code mauricio following code works dream

class program {     static void main(string[] args)     {         dynamic person = new { name = "peter" };         var p = ducktype.as<iperson>(person);          console.writeline(p.name);     } }  public interface iperson {     string name { get; set; } }  public static class ducktype {     private static readonly proxygenerator generator = new proxygenerator();      public static t as<t>(object o)     {         return generator.createinterfaceproxywithouttarget<t>(new ducktypinginterceptor(o));     } }  public class ducktypinginterceptor : iinterceptor {     private readonly object target;      public ducktypinginterceptor(object target)     {         this.target = target;     }      public void intercept(iinvocation invocation)     {         var methods = target.gettype().getmethods()             .where(m => m.name == invocation.method.name)             .where(m => m.getparameters().length == invocation.arguments.length)             .tolist();         if (methods.count > 1)             throw new applicationexception(string.format("ambiguous method match '{0}'", invocation.method.name));         if (methods.count == 0)             throw new applicationexception(string.format("no method '{0}' found", invocation.method.name));         var method = methods[0];         if (invocation.genericarguments != null && invocation.genericarguments.length > 0)             method = method.makegenericmethod(invocation.genericarguments);         invocation.returnvalue = method.invoke(target, invocation.arguments);     } } 

Comments

Popular posts from this blog

c++ - How do I get a multi line tooltip in MFC -

asp.net - In javascript how to find the height and width -

c# - DataTable to EnumerableRowCollection -