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!

Type.GetConstructors() - InvalidProgramException on CF, works fine on the standard framework
QWERTYtech
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
legoman26
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.
MaggieChan
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
Peter Chapman
Nothing but C# or VB is supported on NETCF, so this issue must be because of "ModuleBuilder/ILGenerator" whatever that is.
Cristian Nieva
Probably you need something like this:
instance = constructor.Invoke(null, args);
wms103006
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
Anabhra
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.
viv3
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.
V1ad
"(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!
RabinLin
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!
Aabra
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.
tm9t9
nayob
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!
Zooma
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.