Back to index

lightning-sunbird  0.9+nobinonly
interface-generator.cs
Go to the documentation of this file.
00001 using System;
00002 using System.Runtime.InteropServices;
00003 using System.Reflection;
00004 using System.Reflection.Emit;
00005 using Mozilla.XPCOM;
00006 using MethodDescriptor = Mozilla.XPCOM.TypeInfo.MethodDescriptor;
00007 using TypeTag = Mozilla.XPCOM.TypeInfo.TypeTag;
00008 using ParamFlags = Mozilla.XPCOM.TypeInfo.ParamFlags;
00009 
00010 namespace Mozilla.XPCOM
00011 {
00012 
00013 class InterfaceGenerator
00014 {
00015     static ModuleBuilder module;
00016 
00017     static InterfaceGenerator()
00018     {
00019         AssemblyName an = new AssemblyName();
00020         an.Version = new Version(1, 0, 0, 0);
00021         an.Name = "Mozilla.XPCOM.Interfaces";
00022 
00023         AppDomain curDom = AppDomain.CurrentDomain;
00024         AssemblyBuilder ab =
00025             curDom.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
00026 
00027         module = ab.DefineDynamicModule(an.Name);
00028     }
00029 
00030     String typeName;
00031     TypeBuilder tb;
00032     
00033     internal InterfaceGenerator(String name)
00034     {
00035         typeName = name;
00036     }
00037 
00038     const PropertyAttributes PROPERTY_ATTRS = PropertyAttributes.None;
00039     const MethodAttributes METHOD_ATTRS = MethodAttributes.Public |
00040             MethodAttributes.Abstract | MethodAttributes.Virtual;
00041     PropertyBuilder lastProperty = null;
00042 
00043     Type FixupInterfaceType(TypeInfo.ParamDescriptor desc)
00044     {
00045         try {
00046             return TypeInfo.TypeForIID(desc.GetIID());
00047         } catch (Exception e) {
00048             // Console.WriteLine(e);
00049             return typeof(object);
00050         }
00051     }
00052 
00053     void GenerateInterfaceMethod(TypeInfo.MethodDescriptor desc)
00054     {
00055         if (desc == null || !desc.IsVisible())
00056             return;
00057 
00058         MethodAttributes methodAttrs = METHOD_ATTRS;
00059 
00060         String methodName = desc.name;
00061         if (desc.IsGetter()) {
00062             methodName = "get_" + desc.name;
00063             methodAttrs |= MethodAttributes.SpecialName;
00064         } else if (desc.IsSetter()) {
00065             methodName = "set_" + desc.name;
00066             methodAttrs |= MethodAttributes.SpecialName;
00067         }
00068             
00069         // Fix up interface types in parameters
00070         Type ret = desc.resultType;
00071         if (ret == typeof(object))
00072             ret = FixupInterfaceType(desc.args[desc.args.Length - 1]);
00073         Type[] argTypes = (Type[])desc.argTypes.Clone();
00074         for (int i = 0; i < argTypes.Length; i++) {
00075             if (argTypes[i] == typeof(object))
00076                 argTypes[i] = FixupInterfaceType(desc.args[i]);
00077         }
00078         MethodBuilder meth = tb.DefineMethod(methodName, methodAttrs, ret,
00079                                              desc.argTypes);
00080 
00081         if (desc.IsSetter()) {
00082             if (lastProperty != null && lastProperty.Name == desc.name) {
00083                 lastProperty.SetSetMethod(meth);
00084             } else {
00085                 tb.DefineProperty(desc.name, PROPERTY_ATTRS, desc.resultType,
00086                                   new Type[0]).SetSetMethod(meth);
00087             }
00088             lastProperty = null;
00089         } else if (desc.IsGetter()) {
00090             lastProperty = tb.DefineProperty(desc.name, PROPERTY_ATTRS,
00091                                              desc.resultType, new Type[0]);
00092             lastProperty.SetGetMethod(meth);
00093         } else {
00094             lastProperty = null;
00095         }
00096     }
00097 
00098     internal Assembly Generate()
00099     {
00100         if (module.GetType(typeName) != null)
00101             return module.Assembly;
00102 
00103         String ifaceName = typeName.Replace("Mozilla.XPCOM.Interfaces.", "");
00104         TypeInfo.MethodDescriptor[] descs =
00105             TypeInfo.GetMethodData(ifaceName);
00106 
00107         ushort inheritedMethodCount;
00108         String parentName = TypeInfo.GetParentInfo(ifaceName,
00109                                                    out inheritedMethodCount);
00110         Type parentType;
00111 
00112         if (parentName != null) {
00113             parentName = "Mozilla.XPCOM.Interfaces." + parentName;
00114             parentType = module.Assembly.GetType(parentName);
00115             if (parentType == null) {
00116                 InterfaceGenerator gen = new InterfaceGenerator(parentName);
00117                 parentType = gen.Generate().GetType(parentName);
00118             }
00119         } else {
00120             parentType = typeof(object);
00121         }
00122 
00123         tb = module.DefineType(typeName,
00124                                TypeAttributes.Public | TypeAttributes.Interface,
00125                                parentType);
00126 
00127         for (int i = inheritedMethodCount; i < descs.Length; i++) {
00128             if (descs[i] != null)
00129                 GenerateInterfaceMethod(descs[i]);
00130         }
00131 
00132         tb.CreateType();
00133 
00134         return module.Assembly;
00135     }
00136 
00137 }
00138 
00139 }