Proxying Generic methods

16 views
Skip to first unread message

Craig Neuwirt

unread,
Jan 9, 2009, 12:07:58 PM1/9/09
to castle-pro...@googlegroups.com
Does anyone have any idea the extent of change to DP2 to support proxying generic methods?  Got a few defects from that.

thanks,
  craig

Krzysztof Koźmic

unread,
Jan 9, 2009, 12:45:18 PM1/9/09
to castle-pro...@googlegroups.com
can you provide few failing tests for that?
I'll look into it over the weekend hopefully

Krzysztof

Craig Neuwirt pisze:

Craig Neuwirt

unread,
Jan 9, 2009, 12:56:40 PM1/9/09
to castle-pro...@googlegroups.com
Sure.  I'll create some and put them in DP2 tests with Ignore

Thanks,
  craig

Fabian Schmied

unread,
Jan 10, 2009, 3:33:04 AM1/10/09
to castle-pro...@googlegroups.com
> Does anyone have any idea the extent of change to DP2 to support proxying
> generic methods? Got a few defects from that.

This is actually implemented. There are, however, a few bugs in the
.NET 2.0 CLR (before SP2, at least), which make this really hard to
get right. There are a few workarounds in there (eg. tokens of generic
methods aren't cached, there is this ominous
IInvocation.GetConcreteMethod API, etx), but in principle, it should
work.

What exactly are the defects you have?

Fabian

Craig Neuwirt

unread,
Jan 10, 2009, 1:04:18 PM1/10/09
to castle-pro...@googlegroups.com
Krzysztof, Fabian

It looks like the problem is when creating interfaces proxies while specifying additional interfaces that include generic methods.  I created a unit test to demonstrate the problem.  It is checked in on DP2 trunk with the Ignore attribute.

http://svn.castleproject.org:8080/svn/castle/trunk/Tools/Castle.DynamicProxy2/Castle.DynamicProxy.Tests/GenericMethodsProxyTestCase.cs

I am currently trying to resolve this defect in the WCF integration facility
http://support.castleproject.org/projects/DYNPROXY/issues/view/DYNPROXY-ISSUE-80

Thanks for your help,
  Craig

I also have defects when creating class proxies that call self generic methods.  This is happening when using MS MVC Controllers that have generic methods, but that is something totally different and I'll create more broken tests for that too.

Krzysztof Kozmic

unread,
Jan 12, 2009, 6:03:28 AM1/12/09
to castle-pro...@googlegroups.com
Craig,

The problem is in .cctor, when trying to get MethodInfo of the generic
method with ldtoken.
Unfortunately the API for open generic methods seems to be broken, and
I couldn't find a clean way of getting Methodinfo for such a method.
There are two solutions for that.

1. Try to cache the method in some other way, than by ldtoken
The best I came up with so far is this:
MemberInfo[] methods = type.GetMember( "MethodName",
MemberTypes.Method,
BindingFlags.Instance
|
BindingFlags.Public
|

BindingFlags.NonPublic );
//and now filter out the method we need, and assign it to
the cache field

We get the MethodInfos for not only the generic method, but for all
methods with the same name, and we need to filter it out.

2. Alternatively, easler thing to do, is to not cache the generic
method.

This requires changing ImplementBlankInterface method of
BaseProxyGenerator, so that in foreach loop when current method is open
generic method
it won't get cached.

I don't have access to the repository to create the patch, but it's
straightforward.
With that little change your test, as well as all other pass.

This however means worse performance. Probably someone should create a
solution that does a lot operations with these generic methods, and
profile it to see how well it behaves.
If the performance hit is significant, we might try the 1st approach
and see if it improves things.

Krzysztof


>>> cneu...@gmail.com 2009-01-10 19:04:18 >>>
CONFIDENTIALITY NOTICE
This message is intended exclusively for the individual or entity to which it is addressed. This communication may contain information that is proprietary, privileged, confidential or otherwise legally exempt from disclosure. If you are not the named addressee, you are not authorized to read, print, retain, copy or disseminate this message or any part of it. If you have received this message in error, please delete all copies of this message and notify the sender immediately by return mail or fax ATSI S.A.(+4812) 285 36 04.
Any email attachment may contain software viruses which could damage your own computer system. Whilst reasonable precaution has been taken to minimise this risk, we cannot accept liability for any damage which you sustain as a result of software viruses. You should therefore carry out your own virus checks before opening any attachments.

Craig Neuwirt

unread,
Jan 12, 2009, 8:19:49 AM1/12/09
to castle-pro...@googlegroups.com
Thanks  a bunch for tracking this one down.  Since I think it is a fairly uncommon usage, I think we can live with the performance hit until we can find a better solution or the API gets fixed.

cheers,
  craig

Krzysztof Kozmic

unread,
Jan 12, 2009, 8:39:18 AM1/12/09
to castle-pro...@googlegroups.com
ok, I'll create a patch that does just that when I get home.

Craig Neuwirt

unread,
Jan 12, 2009, 8:46:11 AM1/12/09
to castle-pro...@googlegroups.com
I think Fabian committed the change already.  I'll didn't build from trunk yet, but I did see his commit message.  I'll let you know.

thanks,
  craig

Fabian Schmied

unread,
Jan 12, 2009, 6:54:32 AM1/12/09
to castle-pro...@googlegroups.com
This is definitely a bug in ImplementBlankInterface, which for some
reason doesn't use the "CacheMethodTokens" method. The current
workaround for generic methods in "CacheMethodTokens" is to not cache
them (your solution number 2), so ImplementBlankInterface shouldn't
cache them either.

I'll fix this.

Fabian

PS: Yes, it's inefficient, and maybe we should talk about fixing this,
but I'll make it consistent first, we can optimize later.

Fabian Schmied

unread,
Jan 12, 2009, 7:28:22 AM1/12/09
to castle-pro...@googlegroups.com
Fixed on the trunk. Thanks, Krzystof, for investigating the problem. I
fixed it by making AddFieldToCacheMethodTokenAndStatementsToInitialize
perform the check for generic methods.

Fabian

Craig Neuwirt

unread,
Jan 12, 2009, 9:55:34 AM1/12/09
to castle-pro...@googlegroups.com
Thanks Krzystof and Fabian

GuntherM

unread,
Jan 21, 2009, 7:42:51 PM1/21/09
to Castle Project Users
I am trying to Stub IUnityContainer using Rhino Mocks, and with this
change the problem persists.

The exception is the following:

System.BadImageFormatException: An attempt was made to load a program
with an incorrect format. (Exception from HRESULT: 0x8007000B)
at
IUnityContainerProxy878915366750464caf2756ec11621ba0.RegisterType<TFrom,TTo>
(InjectionMember[] injectionMembers)
at SecurityModule.SecurityModule.RegisterViewsAndServices() in
SecurityModule.cs: line 39
at SecurityModule.SecurityModule.Initialize() in SecurityModule.cs:
line 31
at
SecurityModule.Tests.SecurityModuleTests.InitializeShouldRegisterLoginView
() in SecurityModuleTests.cs: line 41

Other symptoms:
I need to run in debug mode, otherwise I get the following exception
when I try to create the stub.

System.BadImageFormatException: An attempt was made to load a program
with an incorrect format. (Exception from HRESULT: 0x8007000B)
at System.Reflection.Emit.TypeBuilder._TermCreateClass(Int32 handle,
Module module)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.TypeBuilder.CreateType()
at
Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType
() in AbstractTypeEmitter.cs: line 271
at
Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType
() in AbstractTypeEmitter.cs: line 275
at
Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode
(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions
options) in InterfaceProxyWithTargetGenerator.cs: line 326
at
Castle.DynamicProxy.DefaultProxyBuilder.CreateInterfaceProxyTypeWithoutTarget
(Type theInterface, Type[] interfaces, ProxyGenerationOptions options)
in DefaultProxyBuilder.cs: line 70
at
Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyTypeWithoutTarget
(Type theInterface, Type[] interfaces, ProxyGenerationOptions options)
in ProxyGenerator.cs: line 392
at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget
(Type theInterface, Type[] interfaces, ProxyGenerationOptions options,
IInterceptor[] interceptors) in ProxyGenerator.cs: line 262
at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget
(Type theInterface, Type[] interfaces, IInterceptor[] interceptors) in
ProxyGenerator.cs: line 239
at Rhino.Mocks.MockRepository.MockInterface(CreateMockState
mockStateFactory, Type type, Type[] extras) in MockRepository.cs: line
816
at Rhino.Mocks.MockRepository.CreateMockObject(Type type,
CreateMockState factory, Type[] extras, Object[]
argumentsForConstructor) in MockRepository.cs: line 874
at Rhino.Mocks.MockRepository.Stub(Type type, Object[]
argumentsForConstructor) in MockRepository.cs: line 1321
at Rhino.Mocks.MockRepository.GenerateStub(Type type, Object[]
argumentsForConstructor) in MockRepository.cs: line 1343
at Rhino.Mocks.MockRepository.GenerateStub<T>(Object[]
argumentsForConstructor) in MockRepository.cs: line 1332
at
SecurityModule.Tests.SecurityModuleTests.InitializeShouldRegisterLoginView
() in SecurityModuleTests.cs: line 37



On Jan 12, 7:28 am, "Fabian Schmied" <fabian.schm...@gmail.com> wrote:
> Fixed on the trunk. Thanks, Krzystof, for investigating the problem. I
> fixed it by making AddFieldToCacheMethodTokenAndStatementsToInitialize
> perform the check forgenericmethods.
>
> Fabian
>
> On Mon, Jan 12, 2009 at 12:54 PM, Fabian Schmied
>
> <fabian.schm...@gmail.com> wrote:
> > This is definitely a bug in ImplementBlankInterface, which for some
> > reason doesn't use the "CacheMethodTokens" method. The current
> > workaround forgenericmethodsin "CacheMethodTokens" is to not cache
> > them (your solution number 2), so ImplementBlankInterface shouldn't
> > cache them either.
>
> > I'll fix this.
>
> > Fabian
>
> > PS: Yes, it's inefficient, and maybe we should talk about fixing this,
> > but I'll make it consistent first, we can optimize later.
>
> > On Mon, Jan 12, 2009 at 12:03 PM, Krzysztof Kozmic <KKoz...@atsisa.com> wrote:
>
> >> Craig,
>
> >> The problem is in .cctor, when trying to get MethodInfo of thegeneric
> >> method with ldtoken.
> >> Unfortunately the API for opengenericmethodsseems to be broken, and
> >> I couldn't find a clean way of getting Methodinfo for such a method.
> >> There are two solutions for that.
>
> >> 1. Try to cache the method in some other way, than by ldtoken
> >> The best I came up with so far is this:
> >>            MemberInfo[]methods= type.GetMember( "MethodName",
> >> MemberTypes.Method,
> >>                                                  BindingFlags.Instance
> >> |
> >>                                                  BindingFlags.Public
> >> |
>
> >> BindingFlags.NonPublic );
> >>            //and now filter out the method we need, and assign it to
> >> the cache field
>
> >> We get the MethodInfos for not only thegenericmethod, but for all
> >>methodswith the same name, and we need to filter it out.
>
> >> 2. Alternatively, easler thing to do, is to not cache thegeneric
> >> method.
>
> >> This requires changing ImplementBlankInterface method of
> >> BaseProxyGenerator, so that in foreach loop when current method is open
> >>genericmethod
> >> it won't get cached.
>
> >> I don't have access to the repository to create the patch, but it's
> >> straightforward.
> >> With that little change your test, as well as all other pass.
>
> >> This however means worse performance. Probably someone should create a
> >> solution that does a lot operations with thesegenericmethods, and
> >> profile it to see how well it behaves.
> >> If the performance hit is significant, we might try the 1st approach
> >> and see if it improves things.
>
> >> Krzysztof
>
> >>>>> cneuw...@gmail.com 2009-01-10 19:04:18 >>>
> >> Krzysztof, Fabian
>
> >> It looks like the problem is when creating interfaces proxies while
> >> specifying additional interfaces that includegenericmethods.  I
> >> created a
> >> unit test to demonstrate the problem.  It is checked in on DP2 trunk
> >> with
> >> the Ignore attribute.
>
> >>http://svn.castleproject.org:8080/svn/castle/trunk/Tools/Castle.Dynam...
>
> >> I am currently trying to resolve this defect in the WCF integration
> >> facility
> >>http://support.castleproject.org/projects/DYNPROXY/issues/view/DYNPRO...
>
> >> Thanks for your help,
> >>  Craig
>
> >> I also have defects when creating class proxies that call selfgeneric
> >>methods.  This is happening when using MS MVC Controllers that have
> >>generic
> >>methods, but that is something totally different and I'll create more
> >> broken
> >> tests for that too.
>
> >> On Sat, Jan 10, 2009 at 2:33 AM, Fabian Schmied
> >> <fabian.schm...@gmail.com>wrote:
>
> >>> > Does anyone have any idea the extent of change to DP2 to support
> >>proxying
> >>> >genericmethods?  Got a few defects from that.
>
> >>> This is actually implemented. There are, however, a few bugs in the
> >>> .NET 2.0 CLR (before SP2, at least), which make this really hard to
> >>> get right. There are a few workarounds in there (eg. tokens of
> >>generic
> >>>methodsaren't cached, there is this ominous

Krzysztof Kozmic

unread,
Jan 23, 2009, 3:27:52 AM1/23/09
to castle-pro...@googlegroups.com
Create a test case for that.

I assume you're using the trunk, are you?

Krzysztof

Gunther Meyer

unread,
Jan 23, 2009, 9:19:56 AM1/23/09
to castle-pro...@googlegroups.com
Yes, I'm using the trunk.
 
I'm send you a test case this weekend, if that is ok.

Krzysztof Kozmic

unread,
Jan 23, 2009, 9:39:24 AM1/23/09
to castle-pro...@googlegroups.com
yes, that's ok.

Thanks.

Mark

unread,
Jun 7, 2009, 10:58:44 PM6/7/09
to Krzysztof Kozmic, castle-pro...@googlegroups.com
(replying in relation to
http://groups.google.com/group/castle-project-users/browse_thread/thread/291499bdaf73071/64073c72d0b878e8
)

I don't know if you got a test case or what status this is at but I am
still having problems with the latest release.

I am also trying to stub IUnityContainer using Rhino Mocks.

With a bit of investigation I have found that it is this signature
that is causing the problem:

IUnityContainer RegisterType<TFrom, TTo>() where TTo : TFrom;

And I have isolated it to this test which doesn't require a reference
to Unity or RhinoMocks:

[TestClass]
public class UnitTest1
{
// Current implementation fails with:
// System.BadImageFormatException: An attempt was made to


load a program with an incorrect format. (Exception from HRESULT:

0x8007000B).
[TestMethod]
public void CreateInterfaceProxyWithoutTarget_GenericError()
{
Type type = typeof(ISomeInterface);

StandardInterceptor interceptor = new StandardInterceptor
();

List<Type> types = new List<Type>();

object proxy =
new ProxyGenerator().CreateInterfaceProxyWithoutTarget
(type, new Type[] {}, interceptor);
}
}

public interface ISomeInterface
{
ISomeInterface RegisterType<TFrom, TTo>() where TTo : TFrom;
}


Can you update me on the status of this problem?

Thanks!

Mark

Krzysztof Koźmic

unread,
Jun 8, 2009, 2:06:16 AM6/8/09
to Castle Project Users


On Jun 8, 4:58 am, Mark <markspambus...@gmail.com> wrote:
> (replying in relation tohttp://groups.google.com/group/castle-project-users/browse_thread/thr...
> )
>
> I don't know if you got a test case or what status this is at but I am
> still having problems with the latest release.
No I didn't.
>
> I am also trying to stub IUnityContainer using Rhino Mocks.
>
> With a bit of investigation I have found that it is this signature
> that is causing the problem:
>
>    IUnityContainer RegisterType<TFrom, TTo>() where TTo : TFrom;
>
> And I have isolated it to this test which doesn't require a reference
> to Unity or RhinoMocks:
>
> [TestClass]
>     public class UnitTest1
>     {
>         // Current implementation fails with:
>         //  System.BadImageFormatException: An attempt was made to
> load a program with an incorrect format. (Exception from HRESULT:
> 0x8007000B).
>         [TestMethod]
>         public void CreateInterfaceProxyWithoutTarget_GenericError()
>         {
>             Type type = typeof(ISomeInterface);
>
>             StandardInterceptor interceptor = new StandardInterceptor
> ();
>
>             List<Type> types = new List<Type>();
>
>             object proxy =
>                 new ProxyGenerator().CreateInterfaceProxyWithoutTarget
> (type, new Type[] {}, interceptor);
>         }
>     }
>
>     public interface ISomeInterface
>     {
>         ISomeInterface RegisterType<TFrom, TTo>() where TTo : TFrom;
>     }
>
> Can you update me on the status of this problem?
Yes I can: status is - we just learned about it.

Can you create an issue in Donjon for that?
I'll investigate it sometime during the week when I find some free
time.

Thanks,

Krzysztof

Mark

unread,
Jun 8, 2009, 4:01:34 AM6/8/09
to castle-pro...@googlegroups.com
Created issue here:
http://support.castleproject.org/projects/DYNPROXY/issues/view/DYNPROXY-ISSU
E-92

"... status is - we just learned about it."

Sorry - thought the OP in the thread had sent a test.

Thanks for quick response

Mark.

Fabian Schmied

unread,
Jun 8, 2009, 9:27:51 AM6/8/09
to Castle Project Users
> Can you create an issue in Donjon for that?
> I'll investigate it sometime during the week when I find some free
> time.

I've just looked into it after getting the Donjon notification - seems
we are copying the generic parameter constraints in an invalid way.
I'll fix this unless you've already started working on it.

Regards,
Fabian

Krzysztof Koźmic

unread,
Jun 8, 2009, 10:05:21 AM6/8/09
to castle-pro...@googlegroups.com
I haven't. Go ahead.

2009/6/8 Fabian Schmied <fabian....@gmail.com>:

Fabian Schmied

unread,
Jun 8, 2009, 10:50:04 AM6/8/09
to Castle Project Users
> I haven't. Go ahead.

Should be fixed on the trunk.

Fabian

Krzysztof Koźmic

unread,
Jun 8, 2009, 10:59:02 AM6/8/09
to castle-pro...@googlegroups.com
very cool.

thanks

2009/6/8 Fabian Schmied <fabian....@gmail.com>:

Mark

unread,
Jun 8, 2009, 5:57:55 PM6/8/09
to castle-pro...@googlegroups.com
This appears to have fixed my problem.
Thanks for such a quick response!

Mark

-----Original Message-----
From: castle-pro...@googlegroups.com
[mailto:castle-pro...@googlegroups.com] On Behalf Of Fabian Schmied
Sent: Tuesday, 9 June 2009 2:50 a.m.
To: Castle Project Users
Subject: Re: Proxying Generic methods

Reply all
Reply to author
Forward
0 new messages