140 lines
4.4 KiB
C#
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;
|
|
}
|
|
|
|
}
|
|
|
|
}
|