P.S. Just to complicate matters, this code works on the machine we developed
it on, but no others. We can't figure out exactly what the difference
between that machine and any others is.

Have you, by any chance, a more recent version of .NET 2.0 on your
development machine than on the target machine? There have been quite
a high number of issues with generics and Reflection/Reflection.Emit
and some of these have been fixed in e.g. the .NET 2.0 update
installing with the more recent Orcas CTPs and Betas.

In your particular case, your development machine seems to be more
gracious regarding a subtle bug: you don't correctly associate the
generic parameters of your base type with those of your derived type.
With System.Reflection.Emit, this association does not come implicitly
from the parameter names, it must be explicitly specified by calling
MakeGenericType on the base type, specifying the
GenericParameterBuilders of the derived type.

I've updated your sample, which now works as intended on my machine, see below.

There is another issue I've noticed (of course, this is only a quick
sample, but just for completeness): You are assuming that if you get
any generic arguments back from the typeToWrap, then your derived type
should also be generic.

Actually, that might not be what you really want because you also get
something back from Type.GetGenericArguments if you have a closed
generic type (where all type parameters are bound to concrete types).
In that closed generic base type case, you probably don't want your
derived type to be generic at all.

In fact, you could even get a mixture of unbound type parameters and
bound type arguments back; in that case, you would probably only want
your derived type to have the unbound generic arguments. You can check
whether a generic argument is bound or not via its IsGenericParameter
property (true: unbound; false: bound).

Best regards,
Fabian

--- updated sample ---
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

public class NonGenericClass { }

public class GenericClass<T> { }

public class Program
{
 public static void Main ()
 {
   WrapType (typeof (NonGenericClass));    // This works fine
   WrapType (typeof (GenericClass<>));     // This also does :)
 }

 public static Type WrapType (Type typeToWrap)
 {
   // Create the wrapper type
   AppDomain appDomain = Thread.GetDomain ();
   AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly
(new AssemblyName ("Example"),
       AssemblyBuilderAccess.Run);
   ModuleBuilder module = assemblyBuilder.DefineDynamicModule ("Example.dll");
   // FS: changed the next line: removed the base type
   TypeBuilder typeBuilder = module.DefineType ("Wrappers." +
typeToWrap.Name, typeToWrap.Attributes);

   // Setup generic arguments
   Type[] genericParameterTypes = typeToWrap.GetGenericArguments ();

   if (genericParameterTypes.Length > 0)
   {
     string[] genericParameterNames = new string[genericParameterTypes.Length];
     for (int idx = 0; idx < genericParameterTypes.Length; idx++)
       genericParameterNames[idx] = genericParameterTypes[idx].Name;

     GenericTypeParameterBuilder[] genericBuilders =
typeBuilder.DefineGenericParameters (genericParameterNames);

     for (int idx = 0; idx < genericBuilders.Length; idx++)
     {

       genericBuilders[idx].SetGenericParameterAttributes
(genericParameterTypes[idx].GenericParameterAttributes);
       foreach (Type type in
genericParameterTypes[idx].GetGenericParameterConstraints ())
         genericBuilders[idx].SetBaseTypeConstraint (type);
     }

     // FS: added this line to correlate the generic parameters
     typeToWrap = typeToWrap.MakeGenericType (genericBuilders);
   }

   // FS: added this line to set the base type after generic
parameter correlation
   typeBuilder.SetParent (typeToWrap);

   // Return wrapper type
   return typeBuilder.CreateType ();
 }
}

===================================
This list is hosted by DevelopMentor®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to