Code generator that produces class proxies.
Inheritance: CodeGenerator
コード例 #1
0
ファイル: Bridge.cs プロジェクト: Monobjc/monobjc
		/// <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
		}
コード例 #2
0
        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);
            }
        }