How to override a property with Reflection Emit

G

Guest

I have some code to override a property using Reflection Emit:

Zipped example:
http://homepage.ntlworld.com/ricbrown/OverridePropertyWithReflectionEmit.zip
Code: http://homepage.ntlworld.com/ricbrown/Runner.cs.html

However the emitted class does not behave the same way as a class compiled
using the regular csc compiler (.Net 2.0).

The example has a class (SimpleClass) with a single property
(SimpleProperty), and a single sub-class of it (SimpleSubClass) that
overrides the property.

The problem is that when accessing the emitted class using reflection it
throws an 'AmbiguousMatchException'. (line 87 of the example code)

Does anyone have a working example of overriding a property using Reflection
Emit?
Or can anyone point me in the right direction as to how to do this correctly?

I would be grateful for any help.

Thanks,
Richard
 
M

Mattias Sjögren

Richard,
The problem is that when accessing the emitted class using reflection it
throws an 'AmbiguousMatchException'. (line 87 of the example code)

If you compare the compiled and dynamic types I think you'll find that
this is caused by the property in the dynamic class not being marked
correctly as an instance property.

Compiled:

..property instance bool SimpleProperty()
{
.get instance bool
OverridePropertyWithReflectionEmit.SimpleClass::get_SimpleProperty()
}

Dynamic:

..property bool SimpleProperty()
{
.get instance bool DynamicSubClass::get_SimpleProperty()
}

I guess that's enough for GetProperty to see it as a distinct property
rather than an override. Unfortunately I don't think there's much you
can do about it since this flag isn't exposed by Reflection.

The property should still work though, i.e. you should be able to use
it (via a SimpleClass reference) and get the correct return value.


Mattias
 
G

Guest

Mattias,

Thank you so much for such a quick response.
If you compare the compiled and dynamic types I think you'll find that
this is caused by the property in the dynamic class not being marked
correctly as an instance property.

I understand - I had spotted this using the debugger (although I'd love to
know how you got the IlDasm-style view of it?). This means the property is
treated like a 'new' property as described here:
http://blogs.msdn.com/thottams/archive/2006/03/17/553376.aspx
rather than an override. Unfortunately I don't think there's much you
can do about it since this flag isn't exposed by Reflection.

That was a little surprising though. It's a shame I can't generate code
that will make the class behave like the compiled one. :-( Does this mean
the compiler writers use a different API? (CodeDom?)

Thanks again for your help Mattias.

Regards,
Richard
 
M

Mattias Sjögren

Richard,
(although I'd love to know how you got the IlDasm-style view of it?).

I simply saved the dynamic assembly and opened it in Ildasm :)

That was a little surprising though. It's a shame I can't generate code
that will make the class behave like the compiled one. :-(

I noticed that you can get rid of the error by not overriding the
property at all, and only override the get_SimpleProperty method. I'm
not sure if that's recommended or if it gives some nasty side effect,
but at least Peverify doesn't complain.

Does this mean
the compiler writers use a different API? (CodeDom?)

Most compilers use the native COM API; ICeeFileGen,
IMetaDataAssemblyEmit and IMetaDataEmit.


Mattias
 
G

Guest

Mattias,
I simply saved the dynamic assembly and opened it in Ildasm :)

Doh! :) OK, I see how to do that now. Thanks.
I noticed that you can get rid of the error by not overriding the
property at all, and only override the get_SimpleProperty method. I'm
not sure if that's recommended or if it gives some nasty side effect,
but at least Peverify doesn't complain.

I had noticed this too - unfortunately, line 90 of the original example then
fails due to the Reflection with BindingFlags.DeclaredOnly not returning the
overridden property.
Most compilers use the native COM API; ICeeFileGen,
IMetaDataAssemblyEmit and IMetaDataEmit.

It looks the Reflection Emit namespace can't really do what I was after.

However, thank you very much for getting me this far. Your help is very
much appreciated.

Cheers,
Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top