示例#1
0
        protected Type GrabType(Type Copy, TypeBuilder On)
        {
            if (Copy == null)
            {
                return(null);
            }

            if (TypesDone.ContainsKey(Copy))
            {
                return(TypesDone[Copy]);
            }

            if (!Sources.Contains(Copy.Module))
            {
                return(TypeReplaceGenerics(Copy));
            }

            if (Copy.IsByRef)
            {
                return(GrabType(Copy.GetElementType()).MakeByRefType());
            }

            if (Copy.IsArray)
            {
                return(GrabType(Copy.GetElementType()).MakeArrayType());
            }

            if (On == null)
            {
                On = GrabType(Copy.DeclaringType) as TypeBuilder;
            }

            var OurInterfaces = new List <Type>();

            Type[] Interfaces;

            if (!Copy.IsEnum)
            {
                // To not specify an interface implementation if one of the parent types
                // already implements one of the interfaces returned by GetInterfaces.
                foreach (Type T in Copy.GetInterfaces())
                {
                    if (!T.IsAssignableFrom(Copy.BaseType))
                    {
                        OurInterfaces.Add(T);
                    }
                }
                Interfaces = OurInterfaces.ToArray();
            }
            else
            {
                Interfaces = null;
            }

            TypeBuilder Ret;

            if (On == null)
            {
                Ret = Module.DefineType(Copy.Name, Copy.Attributes, GrabType(Copy.BaseType), Interfaces);
            }
            else
            {
                Ret = On.DefineNestedType(Copy.Name, Copy.Attributes, GrabType(Copy.BaseType), Interfaces);
            }

            TypesDone.Add(Copy, Ret);

            // We need to copy over the static constructor explicitly, because it is never called in the IL
            ConstructorInfo StaticConstr = FindStaticConstructor(Copy);

            if (StaticConstr != null)
            {
                GrabConstructor(StaticConstr, Ret);
            }

            // Enum fields need to be copied over on .NET to avoid a TypeLoadException
            // Interestingly, enum types without fields are perfectly fine with mono.
            if (Copy.IsEnum)
            {
                GrabField(Copy.GetField("value__"), Ret);

                foreach (FieldInfo Field in Copy.GetFields(BindingFlags.Public | BindingFlags.Static))
                {
                    if (Field.DeclaringType != Copy)
                    {
                        continue;
                    }
                    GrabField(Field);
                }
            }

            // - If we are copying over a delegate, we need to guarantee that all members are copied over,
            //   if not we'll cause a runtime error somewhere along the pipeline (for example: mono fails
            //   on an assertion).
            // - If we are copying over a class with an abstract parent, we need to copy over all methods
            //   to prevent a TypeLoadException at runtime (non-abstract types containing methods without
            //   a body cause this)
            // Delegates have a native-code constructor that is needed, too
            if (Copy.BaseType == typeof(MulticastDelegate))
            {
                ConstructorInfo NativeCtor = Copy.GetConstructors()[0];
                GrabConstructor(NativeCtor, Ret);

                GrabMethod(Copy.GetMethod("Invoke"), Ret);
                GrabMethod(Copy.GetMethod("BeginInvoke"), Ret);
                GrabMethod(Copy.GetMethod("EndInvoke"), Ret);
            }
            else if (Copy.IsExplicitLayout || Copy.BaseType.IsAbstract || OurInterfaces.Count > 0)
            {
                foreach (MethodInfo Method in Copy.GetMethods())
                {
                    if (Method.DeclaringType != Copy)
                    {
                        continue;
                    }
                    GrabMethod(Method, Ret);
                }

                foreach (MethodInfo Method in Copy.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
                {
                    if (Method.DeclaringType != Copy)
                    {
                        continue;
                    }
                    GrabMethod(Method, Ret);
                }

                foreach (FieldInfo Field in Copy.GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
                {
                    if (Field.DeclaringType != Copy)
                    {
                        continue;
                    }
                    GrabField(Field, Ret);
                }
            }

            if (Copy.IsEnum || Copy.BaseType == typeof(MulticastDelegate))
            {
                Ret.CreateType();
            }

            return(Ret);
        }