public InterfaceWrapperDeclaration(TypeDesc type, TextBlock container, AccessModifierType accessModifier)
            : base(type, container, accessModifier)
        {
            isIUnknown        = type.BaseTypes.Any(x => x.Name == "IUnknown");
            isUserImplemented = InterfaceDeclaration.IsUserImplemented(type);
            ignoreIdentifier  = InterfaceDeclaration.IsWithoutIdentifier(type);

            var methods = type.AllMethods.ToArray();

            vtbl = new InterfaceVtblDeclaration(type, this);

            WriteBaseLine(() => "{");
            AddTextBlock(vtbl);
            WriteLine();

            for (int i = 0; i < methods.Length; i++)
            {
                int        index      = i;
                MethodDesc method     = type.AllMethods.ToArray()[i];
                string     parameters = vtbl.TypeName + "** @this";
                if (MethodDeclaration.GetParameterNames(method).Any())
                {
                    parameters += ", " + MethodDeclaration.GetParameters(method);
                }
                WriteLine(() => "private unsafe delegate " + MethodDeclaration.GetReturnValue(method) + " " + GetDelegateName(index) + "(" + parameters + ");");
            }
            WriteLine();

            WriteLine(() => "private readonly void* reference;");
            if (!ignoreIdentifier)
            {
                WriteLine(() => "private static readonly Guid iid = new Guid(\"" + type.CLSID.ToString() + "\");");
                WriteLine();
                WriteLine(() => AccessModifier + " static unsafe Guid IID");
                WriteLine(() => "{");
                WriteLine(() => "    get");
                WriteLine(() => "    {");
                WriteLine(() => "        return iid;");
                WriteLine(() => "    }");
                WriteLine(() => "}");
            }

            for (int i = 0; i < methods.Length; i++)
            {
                WriteLine();
                bool isNew = ((methods[i].Name == "GetType" || methods[i].Name == "ToString") && !methods[i].Parameters.Any());
                AddTextBlock(new MethodDeclaration(methods[i], this, AccessModifierType.Public, isNew, new DelegateCaller(i, methods[i], this)));
            }

            if (isIUnknown)
            {
                WriteLine();
                WriteLine(() => "void IDisposable.Dispose()");
                WriteLine(() => "{");
                WriteLine(() => "    while ((reference != null) && (Release() > 0))");
                WriteLine(() => "    {");
                WriteLine(() => "    }");
                WriteLine(() => "}");
            }

            WriteLine();
            WriteLine(() => AccessModifier + " unsafe " + TypeName + "(IntPtr value)");
            WriteLine(() => "{");
            WriteLine(() => "    reference = (void*)value;");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => AccessModifier + " unsafe " + TypeName + "(void* value)");
            WriteLine(() => "{");
            WriteLine(() => "    reference = value;");
            WriteLine(() => "}");
            foreach (string baseTypeRefName in type.BaseTypes.Where(x => !InterfaceDeclaration.IsSpecialInterface(x)).Select(x => x.Name))
            {
                WriteLine();
                WriteLine(() => "public static unsafe explicit operator " + TypeName + "(" + baseTypeRefName + " value)");
                WriteLine(() => "{");
                WriteLine(() => "    return new " + TypeName + "(*((void**)(&value)));");
                WriteLine(() => "}");
                WriteLine();
                WriteLine(() => "public static unsafe implicit operator " + baseTypeRefName + "(" + TypeName + " value)");
                WriteLine(() => "{");
                WriteLine(() => "    return new " + baseTypeRefName + "(value.reference);");
                WriteLine(() => "}");
            }

            WriteLine();
            WriteLine(() => "public static unsafe implicit operator IntPtr(" + TypeName + " value)");
            WriteLine(() => "{");
            WriteLine(() => "    return new IntPtr(value.reference);");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public static unsafe implicit operator void*(" + TypeName + " value)");
            WriteLine(() => "{");
            WriteLine(() => "    return value.reference;");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public static unsafe implicit operator " + TypeName + "(IntPtr value)");
            WriteLine(() => "{");
            WriteLine(() => "    return new " + TypeName + "(value);");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public static unsafe implicit operator " + TypeName + "(void* value)");
            WriteLine(() => "{");
            WriteLine(() => "    return new " + TypeName + "(value);");
            WriteLine(() => "}");

            WriteLine();
            WriteLine(() => "public unsafe override bool Equals(object obj)");
            WriteLine(() => "{");
            WriteLine(() => "    " + TypeName + " other = (" + TypeName + ")obj;");
            WriteLine(() => "    return reference == other.reference;");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public unsafe override int GetHashCode()");
            WriteLine(() => "{");
            WriteLine(() => "    return new IntPtr(reference).GetHashCode();");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public unsafe static bool operator ==(" + TypeName + " left, " + TypeName + " right)");
            WriteLine(() => "{");
            WriteLine(() => "    return left.reference == right.reference;");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public unsafe static bool operator !=(" + TypeName + " left, " + TypeName + " right)");
            WriteLine(() => "{");
            WriteLine(() => "    return left.reference != right.reference;");
            WriteLine(() => "}");

            WriteBaseLine(() => "}");
        }
        public InterfaceWrapperDeclaration(TypeDesc type, TextBlock container, AccessModifierType accessModifier)
            : base(type, container, accessModifier)
        {
            isIUnknown = type.BaseTypes.Any(x => x.Name == "IUnknown");
            isUserImplemented = InterfaceDeclaration.IsUserImplemented(type);
            ignoreIdentifier = InterfaceDeclaration.IsWithoutIdentifier(type);

            var methods = type.AllMethods.ToArray();

            vtbl = new InterfaceVtblDeclaration(type, this);

            WriteBaseLine(() => "{");
            AddTextBlock(vtbl);
            WriteLine();

            for(int i = 0; i < methods.Length; i++)
            {
                int index = i;
                MethodDesc method = type.AllMethods.ToArray()[i];
                string parameters = vtbl.TypeName + "** @this";
                if (MethodDeclaration.GetParameterNames(method).Any())
                    parameters += ", " + MethodDeclaration.GetParameters(method);
                WriteLine(() => "private unsafe delegate " + MethodDeclaration.GetReturnValue(method) + " " + GetDelegateName(index) + "(" + parameters + ");");
            }
            WriteLine();

            WriteLine(() => "private readonly void* reference;");
            if (!ignoreIdentifier)
            {
                WriteLine(() => "private static readonly Guid iid = new Guid(\"" + type.CLSID.ToString() + "\");");
                WriteLine();
                WriteLine(() => AccessModifier + " static unsafe Guid IID");
                WriteLine(() => "{");
                WriteLine(() => "    get");
                WriteLine(() => "    {");
                WriteLine(() => "        return iid;");
                WriteLine(() => "    }");
                WriteLine(() => "}");
            }

            for (int i = 0; i < methods.Length; i++)
            {
                WriteLine();
                bool isNew = ((methods[i].Name == "GetType" || methods[i].Name == "ToString") && !methods[i].Parameters.Any());
                AddTextBlock(new MethodDeclaration(methods[i], this, AccessModifierType.Public, isNew, new DelegateCaller(i, methods[i], this)));
            }

            if (isIUnknown)
            {
                WriteLine();
                WriteLine(() => "void IDisposable.Dispose()");
                WriteLine(() => "{");
                WriteLine(() => "    while ((reference != null) && (Release() > 0))");
                WriteLine(() => "    {");
                WriteLine(() => "    }");
                WriteLine(() => "}");
            }

            WriteLine();
            WriteLine(() => AccessModifier + " unsafe " + TypeName + "(IntPtr value)");
            WriteLine(() => "{");
            WriteLine(() => "    reference = (void*)value;");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => AccessModifier + " unsafe " + TypeName + "(void* value)");
            WriteLine(() => "{");
            WriteLine(() => "    reference = value;");
            WriteLine(() => "}");
            foreach (string baseTypeRefName in type.BaseTypes.Where(x => !InterfaceDeclaration.IsSpecialInterface(x)).Select(x => x.Name))
            {
                WriteLine();
                WriteLine(() => "public static unsafe explicit operator " + TypeName + "(" + baseTypeRefName + " value)");
                WriteLine(() => "{");
                WriteLine(() => "    return new " + TypeName + "(*((void**)(&value)));");
                WriteLine(() => "}");
                WriteLine();
                WriteLine(() => "public static unsafe implicit operator " + baseTypeRefName + "(" + TypeName + " value)");
                WriteLine(() => "{");
                WriteLine(() => "    return new " + baseTypeRefName + "(value.reference);");
                WriteLine(() => "}");
            }

            WriteLine();
            WriteLine(() => "public static unsafe implicit operator IntPtr(" + TypeName + " value)");
            WriteLine(() => "{");
            WriteLine(() => "    return new IntPtr(value.reference);");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public static unsafe implicit operator void*(" + TypeName + " value)");
            WriteLine(() => "{");
            WriteLine(() => "    return value.reference;");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public static unsafe implicit operator " + TypeName + "(IntPtr value)");
            WriteLine(() => "{");
            WriteLine(() => "    return new " + TypeName + "(value);");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public static unsafe implicit operator " + TypeName + "(void* value)");
            WriteLine(() => "{");
            WriteLine(() => "    return new " + TypeName + "(value);");
            WriteLine(() => "}");

            WriteLine();
            WriteLine(() => "public unsafe override bool Equals(object obj)");
            WriteLine(() => "{");
            WriteLine(() => "    " + TypeName + " other = (" + TypeName + ")obj;");
            WriteLine(() => "    return reference == other.reference;");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public unsafe override int GetHashCode()");
            WriteLine(() => "{");
            WriteLine(() => "    return new IntPtr(reference).GetHashCode();");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public unsafe static bool operator ==(" + TypeName + " left, " + TypeName + " right)");
            WriteLine(() => "{");
            WriteLine(() => "    return left.reference == right.reference;");
            WriteLine(() => "}");
            WriteLine();
            WriteLine(() => "public unsafe static bool operator !=(" + TypeName + " left, " + TypeName + " right)");
            WriteLine(() => "{");
            WriteLine(() => "    return left.reference != right.reference;");
            WriteLine(() => "}");

            WriteBaseLine(() => "}");
        }