c# - How can I emit a dynamic method returning a ref? -
i'm navigating ins , outs of ref returns, , having trouble emitting dynamic method returns ref.
handcrafted lambdas , existing methods work expected:
class widget { public int length; } delegate ref int widgetmeasurer(widget w); widgetmeasurer getmeasurera() { return w => ref w.length; } static ref int measurewidget(widget w) => ref w.length; widgetmeasurer getmeasurerb() { return measurewidget; }
but emitting dynamic method fails. note: i'm using sigil here. apologies, i'm less familiar system.reflection.emit
.
widgetmeasurer getmeasurerc() { fieldinfo lengthfield = typeof(widget).getfield(nameof(widget.length)); var emitter = emit<widgetmeasurer>.newdynamicmethod() .loadargument(0) .loadfieldaddress(lengthfield) .return(); return emitter.createdelegate(); }
this fails @ newdynamicmethod
, throwing 'the return type contains invalid type (i.e. null, byref)'
. makes sense, since understand under hood widgetmeasurer
returns int32&
.
the question is, there first- or third-party technique can employ emit code mimicking first 2 examples (which empirically know work correctly)? if not, restriction logical one?
edit: i've tried equivalent system.reflection.emit
code , got same exception (as expected):
widgetmeasurer getmeasurerd() { fieldinfo lengthfield = typeof(widget).getfield(nameof(widget.length)); type returntype = typeof(int).makebyreftype(); type[] paramtypes = { typeof(widget) }; dynamicmethod method = new dynamicmethod("", returntype, paramtypes); ilgenerator il = method.getilgenerator(); il.emit(opcodes.ldarg_0); il.emit(opcodes.ldflda, lengthfield); il.emit(opcodes.ret); return (widgetmeasurer)method.createdelegate(typeof(widgetmeasurer)); }
i don't know why limitation exists dynamicmethod, following worked me. 1 difference defining our own dynamic assembly hand. difference since separate assembly, widget
needs public (or if name dynamic assembly appropriately use internalsvisibleto on parent assembly).
static void main(string[] args) { var widget = new widget(); getlengthmeasurer()(widget) = 7; console.writeline(widget.length); } private static widgetmeasurer getlengthmeasurer() { var fieldinfo = typeof(widget).getfield("length"); var asmname = new assemblyname("widgetdynamicassembly." + guid.newguid().tostring()); var asmbuilder = appdomain.currentdomain.definedynamicassembly(asmname, assemblybuilderaccess.runandcollect); var modulebuilder = asmbuilder.definedynamicmodule("<module>"); var typebuilder = modulebuilder.definetype("widgethelper"); var methodbuilder = typebuilder.definemethod("getlength", methodattributes.static | methodattributes.public, typeof(int).makebyreftype(), new[] { typeof(widget) }); var ilgen = methodbuilder.getilgenerator(); ilgen.emit(opcodes.ldarg_0); ilgen.emit(opcodes.ldflda, fieldinfo); ilgen.emit(opcodes.ret); var type = typebuilder.createtype(); var mi = type.getmethod(methodbuilder.name); var del = (widgetmeasurer)mi.createdelegate(typeof(widgetmeasurer)); return del; }
output:
7
Comments
Post a Comment