Mozilla/mozilla/extensions/mono/src/interface-generator.cs
shaver%mozilla.org c367c99af4 initial import of monoconnect^Wxpcom-dotnet^Wextensions/mono code -- not working, not done, not useful to you, not part of the build
git-svn-id: svn://10.0.0.236/trunk@168679 18797224-902f-48f8-a5cc-f745e15eee43
2005-02-01 23:58:57 +00:00

140 lines
4.4 KiB
C#

using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Reflection.Emit;
using Mozilla.XPCOM;
using MethodDescriptor = Mozilla.XPCOM.TypeInfo.MethodDescriptor;
using TypeTag = Mozilla.XPCOM.TypeInfo.TypeTag;
using ParamFlags = Mozilla.XPCOM.TypeInfo.ParamFlags;
namespace Mozilla.XPCOM
{
class InterfaceGenerator
{
static ModuleBuilder module;
static InterfaceGenerator()
{
AssemblyName an = new AssemblyName();
an.Version = new Version(1, 0, 0, 0);
an.Name = "Mozilla.XPCOM.Interfaces";
AppDomain curDom = AppDomain.CurrentDomain;
AssemblyBuilder ab =
curDom.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
module = ab.DefineDynamicModule(an.Name);
}
String typeName;
TypeBuilder tb;
internal InterfaceGenerator(String name)
{
typeName = name;
}
const PropertyAttributes PROPERTY_ATTRS = PropertyAttributes.None;
const MethodAttributes METHOD_ATTRS = MethodAttributes.Public |
MethodAttributes.Abstract | MethodAttributes.Virtual;
PropertyBuilder lastProperty = null;
Type FixupInterfaceType(TypeInfo.ParamDescriptor desc)
{
try {
return TypeInfo.TypeForIID(desc.GetIID());
} catch (Exception e) {
// Console.WriteLine(e);
return typeof(object);
}
}
void GenerateInterfaceMethod(TypeInfo.MethodDescriptor desc)
{
if (desc == null || !desc.IsVisible())
return;
MethodAttributes methodAttrs = METHOD_ATTRS;
String methodName = desc.name;
if (desc.IsGetter()) {
methodName = "get_" + desc.name;
methodAttrs |= MethodAttributes.SpecialName;
} else if (desc.IsSetter()) {
methodName = "set_" + desc.name;
methodAttrs |= MethodAttributes.SpecialName;
}
// Fix up interface types in parameters
Type ret = desc.resultType;
if (ret == typeof(object))
ret = FixupInterfaceType(desc.args[desc.args.Length - 1]);
Type[] argTypes = (Type[])desc.argTypes.Clone();
for (int i = 0; i < argTypes.Length; i++) {
if (argTypes[i] == typeof(object))
argTypes[i] = FixupInterfaceType(desc.args[i]);
}
MethodBuilder meth = tb.DefineMethod(methodName, methodAttrs, ret,
desc.argTypes);
if (desc.IsSetter()) {
if (lastProperty != null && lastProperty.Name == desc.name) {
lastProperty.SetSetMethod(meth);
} else {
tb.DefineProperty(desc.name, PROPERTY_ATTRS, desc.resultType,
new Type[0]).SetSetMethod(meth);
}
lastProperty = null;
} else if (desc.IsGetter()) {
lastProperty = tb.DefineProperty(desc.name, PROPERTY_ATTRS,
desc.resultType, new Type[0]);
lastProperty.SetGetMethod(meth);
} else {
lastProperty = null;
}
}
internal Assembly Generate()
{
if (module.GetType(typeName) != null)
return module.Assembly;
String ifaceName = typeName.Replace("Mozilla.XPCOM.Interfaces.", "");
TypeInfo.MethodDescriptor[] descs =
TypeInfo.GetMethodData(ifaceName);
ushort inheritedMethodCount;
String parentName = TypeInfo.GetParentInfo(ifaceName,
out inheritedMethodCount);
Type parentType;
if (parentName != null) {
parentName = "Mozilla.XPCOM.Interfaces." + parentName;
parentType = module.Assembly.GetType(parentName);
if (parentType == null) {
InterfaceGenerator gen = new InterfaceGenerator(parentName);
parentType = gen.Generate().GetType(parentName);
}
} else {
parentType = typeof(object);
}
tb = module.DefineType(typeName,
TypeAttributes.Public | TypeAttributes.Interface,
parentType);
for (int i = inheritedMethodCount; i < descs.Length; i++) {
if (descs[i] != null)
GenerateInterfaceMethod(descs[i]);
}
tb.CreateType();
return module.Assembly;
}
}
}