private Type CreateInterface(NdrComProxyDefinition intf)
        {
            if (m_types.ContainsKey(intf.Iid))
            {
                return(m_types[intf.Iid]);
            }

            Type existing_type = COMUtilities.GetInterfaceType(intf.Iid);

            if (existing_type != null)
            {
                m_types[intf.Iid] = existing_type;
                return(existing_type);
            }

            ReportProgress($"Creating Interface {intf.Name}");

            TypeBuilder tb = m_module.DefineType(
                MakeIdentifier(intf.Name),
                TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);

            m_types[intf.Iid] = tb;
            tb.SetCustomAttribute(CreateAttribute <ComImportAttribute>());
            tb.SetCustomAttribute(CreateAttribute <GuidAttribute>(intf.Iid.ToString()));
            List <NdrProcedureDefinition> procs = new List <NdrProcedureDefinition>();

            tb.SetCustomAttribute(GetInterfaceTypeAttribute(intf, procs));

            foreach (var proc in procs)
            {
                string name        = MakeIdentifier(proc.Name);
                var    ret_type    = GetTypeDescriptor(proc.ReturnValue);
                var    param_types = proc.Params.Select(p => GetTypeDescriptor(p)).ToList();
                var    methbuilder = tb.DefineMethod(name, MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.NewSlot | MethodAttributes.HideBySig | MethodAttributes.Virtual,
                                                     ret_type.BuiltinType, param_types.Select(p => p.GetParameterType()).ToArray());
                for (int i = 0; i < param_types.Count; ++i)
                {
                    var param_builder = methbuilder.DefineParameter(i + 1, param_types[i].Attributes, $"p{i}");
                    foreach (var attr in param_types[i].CustomAttributes)
                    {
                        param_builder.SetCustomAttribute(attr);
                    }
                }
            }

            m_fixup.Enqueue(tb);

            return(m_types[intf.Iid]);
        }
        private ComInterfaceType GetInterfaceTypeAndProcs(NdrComProxyDefinition proxy, List <NdrProcedureDefinition> procs)
        {
            ComInterfaceType type = ComInterfaceType.InterfaceIsIUnknown;

            if (proxy.BaseIid == COMInterfaceEntry.IID_IDispatch)
            {
                type = ComInterfaceType.InterfaceIsIDispatch;
            }
            else if (proxy.BaseIid == COMInterfaceEntry.IID_IInspectable)
            {
                type = ComInterfaceType.InterfaceIsIInspectable;
            }
            else if (m_proxies.ContainsKey(proxy.BaseIid))
            {
                type = GetInterfaceTypeAndProcs(m_proxies[proxy.BaseIid], procs);
            }

            procs.AddRange(proxy.Procedures);
            return(type);
        }
 private CustomAttributeBuilder GetInterfaceTypeAttribute(NdrComProxyDefinition proxy, List <NdrProcedureDefinition> procs)
 {
     return(CreateAttribute <InterfaceTypeAttribute>(GetInterfaceTypeAndProcs(proxy, procs)));
 }