/// <summary> /// Defines the given class by installing a proxy, that will forward native calls to the corresponding instance. /// </summary> /// <param name = "classGenerator">The class generator.</param> /// <param name = "type">The type.</param> public static void DefineClass (ClassGenerator classGenerator, Type type) { if (type == null) { throw new ArgumentNullException ("type", Resources.CannotDefineObjectiveCClassFromNullType); } // Check if the class is already mapped if (Class.IsMapped (type)) { return; } // Extract class name from attributes String className = ExtractClassName (type); // Check for class existence Class cls = Class.Get (className); if (cls != null) { // Associate the type to the class cls.WrapperType = type.TypeHandle.Value; // Check to see if the class must be intercepted if (NeedInterception (type)) { if (Logger.InfoEnabled) { Logger.Info ("Bridge", "Intercepting 'dealloc' messages for class " + className); } InterceptDeallocFor (cls); } return; } else if(IsNative(type)) { if (Logger.DebugEnabled) { Logger.Debug("Bridge", "Skipping definition for nonexistent native class " + className); } return; } // Objects with an Id base type do not have a superclass String superClassName = null; if (typeof(Id) != type.BaseType) { // Extract class name from attributes superClassName = ExtractSuperClassName (type); // Get the superclass Class superCls = Class.Get (superClassName); if (superCls == null) { throw new ObjectiveCException (String.Format (CultureInfo.CurrentCulture, Resources.CannotDefineClassBecauseSuperclassDoesNotExists, type, superClassName)); } } if (Logger.DebugEnabled) { Logger.Debug ("Bridge", "Defining class " + type + " <-> " + className + " : " + superClassName ?? "Id"); } // Collects the informations needed for class generation VariableTuple[] variableTuples = CollectInstanceVariables (type); MethodTuple[] instanceMethods = CollectInstanceMethods (type); MethodTuple[] classMethods = CollectStaticMethods (type); // Generates the class proxy with the associated structures Type proxyType = classGenerator.DefineClassProxy (type, instanceMethods, classMethods); // Create the peer native class String[] ivarNames = Array.ConvertAll (variableTuples, tuple => tuple.Name); IntPtr[] ivarTypes = Array.ConvertAll (variableTuples, tuple => tuple.Type.TypeHandle.Value); cls = CreateClass (className, superClassName, ivarNames, ivarTypes); // Add instance methods #if USE_CLOSURES foreach (MethodTuple tuple in instanceMethods) { MethodInfo methodInfo = proxyType.GetMethod(tuple.ProxyMethodInfo.Name); IntPtr handle = methodInfo.MethodHandle.Value; AddMethod(cls.pointer, false, handle, tuple.Selector, ObjectiveCEncoding.GetSignature(methodInfo)); } #else String[] methodNames = Array.ConvertAll (instanceMethods, tuple => tuple.Selector); IntPtr[] methodImplementations = Array.ConvertAll (instanceMethods, tuple => tuple.GetFunction (proxyType)); String[] methodEncoding = Array.ConvertAll (instanceMethods, tuple => ObjectiveCEncoding.GetSignature (tuple.MethodInfo)); AddMethods (cls.pointer, false, methodNames, methodImplementations, methodEncoding); #endif // Add class methods #if USE_CLOSURES foreach (MethodTuple tuple in classMethods) { MethodInfo methodInfo = proxyType.GetMethod(tuple.ProxyMethodInfo.Name); IntPtr handle = methodInfo.MethodHandle.Value; AddMethod(cls.pointer, true, handle, tuple.Selector, ObjectiveCEncoding.GetSignature(methodInfo, 0)); } #else methodNames = Array.ConvertAll (classMethods, tuple => tuple.Selector); methodImplementations = Array.ConvertAll (classMethods, tuple => tuple.GetFunction (proxyType)); methodEncoding = Array.ConvertAll (classMethods, tuple => ObjectiveCEncoding.GetSignature (tuple.MethodInfo, 0)); AddMethods (cls.pointer, true, methodNames, methodImplementations, methodEncoding); #endif }
private void TestClass(Type classType, Type referenceType, bool is64Bits) { counter++; DynamicAssembly assembly = new DynamicAssembly(DynamicAssemblyHelper.GetAssemblyName(this, counter), "MyModule"); MethodTuple[] instanceMethods = Bridge.CollectInstanceMethods(classType); Assert.IsTrue(Array.TrueForAll(instanceMethods, m => !m.MethodInfo.IsStatic)); MethodTuple[] staticMethods = Bridge.CollectStaticMethods(classType); Assert.IsTrue(Array.TrueForAll(staticMethods, m => m.MethodInfo.IsStatic)); ClassGenerator generator = new ClassGenerator(assembly, is64Bits); Type proxyType = generator.DefineClassProxy(classType, instanceMethods, staticMethods); try { assembly.Save(); Type type = assembly.GetType(proxyType.FullName); DynamicAssemblyHelper.Compare(referenceType, type); } catch (Exception ex) { Assert.Fail("Type retrieval failed with " + ex); } }