Type.GetConstructors() - InvalidProgramException on CF, works fine on the standard framework

I have a piece of generated code that the CF (2.0SP1, August patch) just won't accept.
The code is working just fine on the big framework, but mscorlib in CF gives me an InvalidProgramException.

The context of the call to Type.GetConstructors():
protected virtual object CreateInstanceWrapper(Type type, params object[] args)
{
object instance;
#if !CF
instance = Activator.CreateInstance( type, args );
#else
ConstructorInfo constructor;
Type[] argTypes;

argTypes = GetTypeArray(args);
constructor = type.GetConstructor(argTypes);

if (constructor == null) throw new ArgumentException("There is no matching constructor");

instance = Activator.CreateInstance(type);
constructor.Invoke(instance, args);
#endif
return instance;
}


And the IL code for the constructor (which seems ok to me):
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 2
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
}


Any ideas why mscorlib on CF throws InvalidProgramExceptions on this
Thanks!



Answer this question

Type.GetConstructors() - InvalidProgramException on CF, works fine on the standard framework

  • logogamer

    Is your constructor private In that case you'd need to specify binding flags as described here:

    http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=701087&SiteID=1

    Or perhaps there's no constructor which takes arguments of types specified in Type array



  • khaleel

    Oh, sorry about not explaining that GetTypeArray()-method. That's a method in my class that does _exactly_ what your snippet does.

    What I'm trying to do is to customize an open source proxy generation library to make it work on CF.
    That library uses the ILGenerator and System.Reflection.Emit to produce its proxies during runtime. However, since System.Reflection.Emit is excluded from CF, I use a tool to generate those runtime proxies (dynamic assembly) to save them to an file assembly. That assembly is what I'm trying to use with CF.

    Since it's important to refer to the CF mscorlib when running csc, I guess that you must add a reference to the CF mscorlib when emitting IL code/saving dynamic modules as well Maybe that's what happening here. But it is very strange though, because it is only the GetConstructor(s)-method that fails. I can without any troubles obtain references to MethodInfo's on other methods than the constructors.

    And worth to mention.. I added a bogus empty constructor (the one in my initial posting) to check if it was some type load failure, because my real constructor has several arguments from other libraries. So by using an empty constructor I reduce the problem from being related to the type loader.

    Thanks anyway!



  • Harshil_Patel_5326c0

    Probably you need something like this:

    instance = constructor.Invoke(null, args);



  • samltd

    What do you mean "compiled with CSC" As opposed to what VB

    Also, if you want default constructor, just call Activator.CreateInstance().

    It might be helpful to remove your conditional compilation and see if this code works in desktop.



  • Prerak Shah

    Yeah, sure.. If that is a problem when I come so far. Right now, the problem is about getting hold of a ConstructorInfo reference.

    I've been trying to investigate the System.Type reference in the debugger and Type.GetConstructors() fails, Type.GetConstructor(Type[]) fails. Type.GetMethods does also fail, but if I try GetMethod("set_MyProperty") (or something else in my class that isn't a constructor) everything is fine.

    It's only the constructors that fails, only on CF, never on the complete framework.
    And since I've found several posts on the blogosphere and in newsgroups about people complaining about the minimal overloads on the Activator.CreateInstance, I thought that this issue might be related to why you guys didn't add the Activator.CreateInstance(Type, object[]) overload.
    That's why I posted my question to this forum. :)

    I mean, my CreateInstanceWrapper is quite simple, so I guess that you would have added a similar implementation to CF if it were that simple.

    I also saw an answer from the lead program manager of CF that had a solution of "good design" that included a public method on all classes which initialized the class. But since our classes needs immutability we must rely on constructor injected dependencies and can't use a design like that.

    For me, it feels simple to add this missing overload to the CF System.Activator. But you guys probably have some good reason for why it's missing, right



  • Doug 123

    That's right, in ".Net Framework", but you're using it in ".Net Compact Framework" which only supports VB and C#. < xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

     

    Perhaps there's a good reason Reflection.Emit is not supported on NETCF...

     

    And, by the way, I wonder which assemblies are referenced in the manifest of this generated module…

    For some reason I suspect that would be desktop’s assemblies and desktop assemblies are not allowed on NETCF.

     



  • Poledog

    This is "whatever that is":
    http://msdn2.microsoft.com/en-us/library/system.reflection.emit.modulebuilder.aspx
    You'll find an code sample in C# and VB on that page if you want to see how it can be used.

    To describe the context of the problem once again; I'm generating an assembly for NETCF using the code generation tools found in .net framework. The ModuleBuilder/ILGenerator is part of that set of tools.


  • RBecker

    I have now tried to instantiate the type by using the new operator in code, and everything works fine! However, the exception still remains when trying to get a reference to a ConstructorInfo for the type.

    A first chance exception of type 'System.InvalidProgramException' occurred in mscorlib.dll
    at System.RuntimeType.GetMemberCons()
    at System.RuntimeType.GetConstructorImplInternal()
    at System.RuntimeType.GetConstructorImpl()
    at System.Type.GetConstructor()
    at System.Type.GetConstructor()


    The strange thing here is that the IL for a constructor that was compiled with CSC looks the same as the generated IL, when using ILDASM. But for the class compiled with CSC, there's no problem getting the default constructor. To get the default constructor I'm using GetConstructor(new Type[0]) on the type object.

    Since the IL looks the same (except for a .maxstack 2 with ILGenerator and .maxstack 8 with CSC), I wonder if there might be something with the module.




  • T.Gunaseelan

    Er, no. I thought I was pretty clear in this statement:
    "(except for a .maxstack 2 with ILGenerator and .maxstack 8 with CSC)"

    With that I meant "compiled with CSC opposed to code emitted with ModuleBuilder/ILGenerator".
    I'm sorry if I was unclear in my statement.

    Thanks for the tip!


  • mshvw

    Well, I do reference the assembly in order to get it deployed with my device project. But I haven't tried that yet. Thanks for the tip!



  • Shawn Wildermuth - MVP &amp;#40;C&amp;#35;&amp;#41;

    No, it's public. From my other post:

    > .method public hidebysig specialname rtspecialname
    > instance void .ctor() cil managed

    And yeah, I thought it could be a mismatch of the type array, so I created the empty constructor (above). However, I should not get an exception if that were the case, only a null reference back from the GetConstructor method.

    The InvalidProgramException is thrown by some internal method, System.RuntimeType.GetConstructorImpl and not by the Type class itself.



  • GoodMorningSky

    Nothing but C# or VB is supported on NETCF, so this issue must be because of "ModuleBuilder/ILGenerator" whatever that is.



  • Nick W.

    Johan,

    I don't believe that GetTypeArray() is supported by the CF... V2 SP1 or any other version, as far as I can tell. You say this is in "generated code"... generated by what Also, I'm not sure why that would have compiled... I would have thought it would have given you an error. Are you sure it's correctly being compiled against as a CF project and not against the desktop framework

    Since GetTypeArray() is not available for CF, you should try something like this instead:

    Type[] argTypes = new Type[args.Length];
    for(int x = 0; x < args.Length; x++)
    {
    argTypes[x] = args[x].GetType();
    }

    Hope that helps,
    --Jeff


  • anubisascends

    One other thing to check - if you reference the generated proxy assembly in your CF project - are you able to instantiate your class using one of the "problematic" constructors

  • Type.GetConstructors() - InvalidProgramException on CF, works fine on the standard framework