Пример #1
0
            public Protocol(Net2ObjC n2c, InterfaceFacet facet, bool writeImplementation)
            {
                string baseProtocol           = "System_Object";
                string adoptionProtocolSuffix = "_";
                string adoptionProtocolName   = facet.ObjCFacet.Type + adoptionProtocolSuffix;

                if (!writeImplementation)
                {
                    // write adoption protocol
                    string protocolSuffix = adoptionProtocolSuffix;
                    ProtocolName = adoptionProtocolName;

                    // build list of base protocols
                    BaseProtocols = baseProtocol + protocolSuffix;
                    foreach (ImplementedInterfaceFacet interfaceFacet in facet.ImplementedInterfaces)
                    {
                        string interfaceName = interfaceFacet.ObjCFacet.Type + protocolSuffix;
                        if (n2c.Config.GenerateFacetBinding(interfaceFacet))
                        {
                            BaseProtocols += (", " + interfaceName);
                        }
                        else
                        {
                            BaseProtocols += (" /*, " + interfaceName + "*/ ");
                        }
                    }
                }
                else
                {
                    // write implementation protocol
                    string protocolSuffix = "";
                    ProtocolName = facet.ObjCFacet.Type + protocolSuffix;

                    // build list of base protocols
                    BaseProtocols = adoptionProtocolName + ", " + baseProtocol;
                    foreach (ImplementedInterfaceFacet interfaceFacet in facet.ImplementedInterfaces)
                    {
                        string interfaceName = interfaceFacet.ObjCFacet.Type + protocolSuffix;
                        if (n2c.Config.GenerateFacetBinding(interfaceFacet))
                        {
                            BaseProtocols += (", " + interfaceName);
                        }
                        else
                        {
                            BaseProtocols += (" /*, " + interfaceName + "*/ ");
                        }
                    }
                }
            }
Пример #2
0
        public void GenerateAssemblyCodeFromTemplate(AssemblyFacet assemblyFacet)
        {
            string templateFileName = null;

            // Create the template host
            TemplatingEngineHost templateHost = new TemplatingEngineHost();

            templateHost.TemplateFileValue = "Net2ObjC.tt";

            // utilise the runtime template
            N2ObjC               = new Net2ObjC();
            N2ObjC.Host          = templateHost;
            N2ObjC.AssemblyFacet = assemblyFacet;
            N2ObjC.XMLFilePath   = XMLFile;

            // run the template
            LogText = N2ObjC.TransformText();

            bool saveLog = false;

            // save the logOutput if required
            if (saveLog)
            {
                string outputFileName = Path.GetFileNameWithoutExtension(templateFileName);
                outputFileName = Path.Combine(Path.GetDirectoryName(templateFileName), outputFileName);
                outputFileName = outputFileName + "1" + templateHost.FileExtension;
                File.WriteAllText(outputFileName, LogText);
            }

            // format errors
            if (templateHost.Errors != null)
            {
                StringBuilder errors = new StringBuilder();
                foreach (CompilerError error in templateHost.Errors)
                {
                    errors.AppendLine(error.ToString());
                    errors.AppendLine(" ");
                }
                ErrorText = errors.ToString();
            }
        }
Пример #3
0
        public void GenerateAssemblyCodeFromTemplate(AssemblyFacet assemblyFacet)
        {
            string templateFileName = null;

            // Create the template host
            TemplatingEngineHost templateHost = new TemplatingEngineHost();
            templateHost.TemplateFileValue = "Net2ObjC.tt";

            // utilise the runtime template
            N2ObjC = new Net2ObjC();
            N2ObjC.Host = templateHost;
            N2ObjC.AssemblyFacet = assemblyFacet;
            N2ObjC.XMLFilePath = XMLFile;

            // run the template
            LogText =  N2ObjC.TransformText();

            bool saveLog = false;

            // save the logOutput if required
            if (saveLog)
            {
                string outputFileName = Path.GetFileNameWithoutExtension(templateFileName);
                outputFileName = Path.Combine(Path.GetDirectoryName(templateFileName), outputFileName);
                outputFileName = outputFileName + "1" + templateHost.FileExtension;
                File.WriteAllText(outputFileName, LogText, templateHost.FileEncoding);
            }

            // format errors
            if (templateHost.Errors != null)
            {
                StringBuilder errors = new StringBuilder();
                foreach (CompilerError error in templateHost.Errors) {
                    errors.AppendLine(error.ToString());
                    errors.AppendLine(" ");
                }
                ErrorText = errors.ToString();
            }
        }
Пример #4
0
            public Accessor(Net2ObjC n2c, CodeFacet facet, Dictionary <string, object> options = null)
            {
                Name        = facet.Name;
                Description = facet is PropertyFacet ? "property" : "field";

                // define getters and setters
                GetterName     = Name.FirstCharacterToLower();
                SetterName     = "set" + Name.FirstCharacterToUpper();
                ObjCMethodType = null;
                if (facet.IsStatic)
                {
                    ObjCMethodType = "+";

                    // decorate class accessor method names known to be unsafe
                    if (n2c.UnsafeObjCClassMethodNames().Contains(GetterName))
                    {
                        GetterName += "_";
                        SetterName += "_";
                    }
                }
                else
                {
                    ObjCMethodType = "-";
                }

                string accessorType = facet.Type;

                ObjCTypeDecl     = n2c.ObjCTypeDeclFromManagedFacet(facet);
                IsObjectProperty = n2c.ObjCRepresentationIsObject(facet);
                MonoObjectPtr    = "MonoObject *";

                // some NSObject properties need a bit of TLC
                BaseProperties = new List <string> {
                    "description"
                };

                // property storage and evaluation
                PropertyAttributes = "";
                PropertyStorage    = "_" + GetterName;
                if (facet.IsStatic)
                {
                    PropertyStorage = "m" + PropertyStorage;
                    if (IsObjectProperty)
                    {
                        n2c.StaticObjectPropertyStorageNames.Add(PropertyStorage);
                    }
                }
                DoPropertyEqualityTest = "";
                if (IsObjectProperty)
                {
                    // test if mono object pointer and property storage reference the same managed object
                    DoPropertyEqualityTest = string.Format("if ([self object:{0} isEqualToMonoObject:{1}]) return {0};", PropertyStorage, ManagedVariableName);
                }

                // instance property.
                if (!facet.IsStatic)
                {
                    string attributes = "nonatomic";

                    // object property attributes
                    if (n2c.ObjCRepresentationIsObject(facet))
                    {
                        attributes += ", strong";
                    }
                    if (!facet.IsWritable)
                    {
                        attributes += ", readonly";
                    }
                    PropertyAttributes = String.Format("({0}) ", attributes);
                }

                // create Obj-C representation of managed object
                ManagedValueToObjC = n2c.ManagedValueToObjc(ManagedVariableName, facet);
                ObjCValueToMono    = n2c.ObjCValueToManaged(ObjCVariableName, ObjCTypeDecl, facet);
                ObjCTypeAssociation objCTypeAssociate = n2c.ObjCTypeAssociate(facet);

                // form mono method invocation name.
                // a prefix may be required, for instance when calling explicit interface properties.
                string monoMethodPrefix = "";

                if (options != null)
                {
                    if (options.ContainsKey("cAPIMethodPrefix"))
                    {
                        monoMethodPrefix = (string)options["cAPIMethodPrefix"];
                    }
                }
                MonoInvocationName = monoMethodPrefix + Name;

                IsValid = true;
            }
Пример #5
0
        //
        // WriteAllText
        //
        public static void WriteAllText(Net2ObjC.OutputType outputType, string contentFile, string content)
        {
            // .NET default string encoding is Unicode.
            // Here we choose UTF8 though.
            // TODO: allow choice of encoding
            Encoding encoding = Encoding.UTF8;
            string outputFolder = Path.GetDirectoryName(contentFile);

            // Content file contains an entire assembly representation
            // Xcode can choke on large single file assemblies.
            // Give it a break and split the content based on tags embedded in the content
            string tagStart = "//++" + Net2ObjC.GenToolName;
            string tagEnd = "//--" + Net2ObjC.GenToolName;
            List<string> fileList = new List<string>();

            int idxLimit = -1;
            int idxStart = 0, idxEnd = 0;
            do
            {
                idxStart = content.IndexOf(tagStart, idxStart);
                if (idxLimit == -1) idxLimit = idxStart;
                if (idxStart != -1)
                {
                    // get the tagged range
                    idxEnd = content.IndexOf(tagEnd, idxStart);
                    if (idxEnd == -1)
                    {
                        throw new Exception("End tag missing.");
                    }
                    idxEnd += tagEnd.Length;

                    // get the substring to export
                    string output = content.Substring(idxStart, idxEnd - idxStart);

                    // get output file
                    int idxLineEnd = output.IndexOf("\r\n");
                    if (idxLineEnd == -1)
                    {
                        idxLineEnd = output.IndexOf("\n");
                    }
                    int idxFilenameStart = tagStart.Length;
                    idxLineEnd -= idxFilenameStart;
                    string outputFileName = output.Substring(tagStart.Length, idxLineEnd).Trim();
                    string outputFilePath = Path.Combine(outputFolder, outputFileName);

                    // persist the filename for later processing
                    fileList.Add(outputFileName);

                    if (outputType == Net2ObjC.OutputType.Implementation)
                    {
                        string importFileName = Path.GetFileNameWithoutExtension(contentFile) + ".h";
                        string import = String.Format("#import \"{0}\"{1}", importFileName, Environment.NewLine);
                        output = import + output;
                    }

                    // export it
                          StreamWriter sw = new StreamWriter(outputFilePath, false, encoding);
                     sw.NewLine = "\n";
                          sw.Write(output);
                     sw.Close();

                          // Legacy
                    //File.WriteAllText(outputFilePath, output, encoding);

                    // move the cursor
                    idxStart = idxEnd;
                    idxEnd = idxStart;
                }

            } while (idxStart != -1);

            // truncate the content to before the first tag
            string truncatedContent = content.Substring(0, idxLimit);
            StringBuilder sb = new StringBuilder( truncatedContent );
            string outputFormat = "";

            // get a format string for use when referencing extracted files in content file
            if (outputType == Net2ObjC.OutputType.Interface)
            {
                outputFormat = "#import \"{0}\"";
            }
            else
            {
                outputFormat = "// " +  Net2ObjC.GenToolName + " made {0}";
            }

            // reference extract files either as an import or as a comment as appropriate
            foreach (string item in fileList) {
                sb.AppendFormat(outputFormat, item);
                sb.Append(Environment.NewLine);
            }

            // output the remaining content
            if (content != null)
            {
                    StreamWriter sw = new StreamWriter(contentFile, false, encoding);
                    sw.NewLine = "\n";
                    sw.Write(sb.ToString());
                    sw.Close();

                    // Legacy
               //File.WriteAllText(contentFile, sb.ToString(), encoding);
            }
        }
Пример #6
0
            public void ProcessParameters(Net2ObjC n2c, MethodFacet facet, Dictionary <string, object> options = null)
            {
                int idx = 0;

                foreach (ParameterFacet parameter in facet.Parameters)
                {
                    // Known issues:
                    //
                    // 1. Rendering of T[]& fails as in System.Array:Resize<T>(ref T[], int)
                    // <Parameter Name="array" Type="T[]&" ElementType="T[]" IsByRef="True" ContainsGenericParameters="True"/>
                    // Issue : T[]& renders as T**
                    // Workaround: exclude in config.objc.xml like so <string>System.Array:Resize</string>
                    // Suggested fix: provide a separate Element xml element to detail the ElementType more fully.

                    // if the mono parameters is passed by ref then strip
                    // the suffix to enable type association
                    string monoParameterType = parameter.Type;
                    if (parameter.IsByRef || parameter.IsPointer)
                    {
                        monoParameterType = parameter.ElementType;
                    }

                    //
                    // build the ObjC method interleaved parameter representation
                    // eg: name1:(int32_t)p1 name2:(int64_t)p2 name3:(NSString *)p3
                    //
                    string objCParamTypeDecl     = null;
                    bool   objCParameterIsObject = true;

                    //
                    // Get the ObjC type associated with the parameter.
                    //
                    ObjCTypeAssociation    objCTypeAssociate    = n2c.ObjCTypeAssociate(parameter);
                    ManagedTypeAssociation managedTypeAssociate = null;
                    if (objCTypeAssociate != null)
                    {
                        //
                        // If the parameter is an array, say Int64[], then its Obj-C rep will be System.Array
                        // The mono type association however must reflect the represented type, Int64.
                        //
                        if (parameter.IsArray)
                        {
                            ObjCTypeAssociation objCRepresentedTypeAssociate = n2c.ObjCTypeAssociate(parameter.ElementType);
                            if (objCRepresentedTypeAssociate != null)
                            {
                                managedTypeAssociate = objCRepresentedTypeAssociate.ManagedTypeAssociate;
                            }
                        }

                        if (managedTypeAssociate == null)
                        {
                            managedTypeAssociate = objCTypeAssociate.ManagedTypeAssociate;
                        }

                        objCParamTypeDecl     = objCTypeAssociate.ObjCTypeDecl;
                        objCParameterIsObject = objCTypeAssociate.IsNSObject;
                    }
                    else
                    {
                        //
                        // Generate default objC representations
                        //
                        objCParamTypeDecl     = n2c.ObjCTypeDeclFromManagedFacet(parameter);
                        objCParameterIsObject = n2c.ObjCRepresentationIsObject(parameter);
                    }

                    // if parameter is an interface then use adoption conforming type ie: id <typename>
                    if (parameter.IsInterface)
                    {
                        objCParamTypeDecl = n2c.ObjCConformingTypeFromObjCTypeDecl(objCParamTypeDecl, false);
                    }
                    if (parameter.IsByRef || parameter.IsPointer)
                    {
                        objCParamTypeDecl += "*";                           // add additional indirection
                    }

                    //
                    // Build the mono method argument invocation signature
                    //
                    if (idx > 0)
                    {
                        MonoSigBuilder.Append(",");
                    }
                    string monoParameterTypeInvoke = null;

                    // if type is a GenericParameter defined by the class, as opposed to via a method like so Method<T>(T).
                    // in this case we want to identify the parameter by its position as this makes it simple
                    // to build the required signature at run time
                    if (parameter.IsGenericParameter && !parameter.DeclaredByMethod)
                    {
                        // generic parameters must have an associate
                        if (managedTypeAssociate == null)
                        {
                            throw new Exception("Missing managed type association for generic parameter.");
                        }

                        monoParameterTypeInvoke = managedTypeAssociate.ManagedTypeInvoke;
                        if (parameter.IsArray)
                        {
                            monoParameterTypeInvoke += "[]";
                        }

                        // in order for the C api to substitute the correct type at run time
                        // the generic parameter position needs to be indicated.
                        monoParameterTypeInvoke = string.Format(monoParameterTypeInvoke, parameter.GenericParameterPosition);
                    }

                    // if parameter is declared by the method like so Method<T>(T) then we want to preserve the type name
                    // as this constitutes part of the method signature this is used to lookup the generic method for inflation
                    else if (parameter.IsGenericParameter && parameter.DeclaredByMethod)
                    {
                        // we expect to be opertaing on a generic method definition
                        if (!facet.IsGenericMethodDefinition)
                        {
                            throw new Exception("Generic method definition expected.");
                        }

                        // the type sig will be something like Declaring.Type+T but the embedded API sig
                        // uses just the type parameter name T
                        int symbolIndex = monoParameterType.IndexOf('+');
                        if (symbolIndex == -1)
                        {
                            throw new Exception("Missing nested type symbol for generic parameter.");
                        }
                        monoParameterTypeInvoke = monoParameterType.Substring(symbolIndex + 1);
                        if (parameter.IsArray)
                        {
                            monoParameterTypeInvoke += "[]";
                        }
                    }
                    else
                    {
                        monoParameterTypeInvoke = n2c.ManagedTypeInvokeFromManagedType(monoParameterType);
                    }

                    // Note that we use a separate variable to hold the actual type sig used in the in mono_method_desc call
                    // as the signature may need to be specfically modified for the mono_method_desc API.
                    string monoParameterTypeInvoke_ = monoParameterTypeInvoke;

                    // The mono_method_desc * APIs prefix nested classes with a '/' rather than a '+' to conform with IL/CTS conventions
                    // The approach used here is trivial and is likely fragile.
                    // We probably need a separate mono param type builder like that found in debug-helpers.c append_class_name().
                    // Note that Delegates will present as nested classes.
                    // Also note that although we have an IsNested property we shouldn't use it as a conditional test for this operation
                    // as generic types with nested type paramaters such as System.Collections.Generic.IEnumerable`1<A.B+C>
                    // won't identify as nested.
                    monoParameterTypeInvoke_ = monoParameterTypeInvoke_.Replace("+", "/");

                    // add type signature and access modifier
                    MonoSigBuilder.Append(monoParameterTypeInvoke_);
                    if (parameter.IsPointer)
                    {
                        MonoSigBuilder.Append("*");
                    }
                    if (parameter.IsByRef)
                    {
                        MonoSigBuilder.Append("&");                         // the signature needs to express by ref
                    }

                    // Build ObjC parameter name.
                    // In order to represent overloaded methods effectively the
                    // ObjC paramter name is constructed as follows:
                    // Managed parameter name + Managed parameter type + Ref
                    string objCParamName = ObjCIdentifierFromManagedIdentifier(parameter.Name);

                    // If the method is overloaded by parameter then make the ObjC method
                    // name unique by including type info in the name.
                    //
                    // Managed methods are overloaded by name only.
                    // The Obj-C metjods representation uses interleaved parameters which may
                    // be sufficient to produce a unique method signature.
                    //
                    // If however a managed method overload differs only in the type of its parameters
                    // (the managed method name, parameter count and parameter names all being equal)
                    // then the Obj-C interleaved parameters will include type info.
                    string objCParamOverloadSuffix = "";
                    if (facet.IsOverloadedParameterMethod)
                    {
                        // We adopt a minimal as opposed to a full type repesentation here in order
                        // to minimize the parameter length.
                        // Time will tell how it flies.
                        objCParamOverloadSuffix = n2c.ObjCMinimalIdentifierFromManagedIdentifier(monoParameterTypeInvoke);

                        if (parameter.IsArray)
                        {
                            objCParamOverloadSuffix += "Array";
                        }

                        if (parameter.IsPointer)
                        {
                            objCParamOverloadSuffix += "Ptr";
                        }
                    }
                    if (parameter.IsByRef)
                    {
                        objCParamOverloadSuffix += "Ref";
                    }

                    if (objCParamOverloadSuffix.Length > 0)
                    {
                        objCParamName += objCParamOverloadSuffix.FirstCharacterToUpper();
                    }

                    // append the complete interleaved parameter expression
                    if (idx == 0)
                    {
                        if (n2c.AppendFirstArgSignatureToMethodName)
                        {
                            // the leading underscore helps identify the preceding characters as the managed method name
                            ObjCMethodName += "_with";
                            ObjCParameterBuilder.AppendFormat("{0}", objCParamName.FirstCharacterToUpper());
                        }
                    }
                    else
                    {
                        ObjCParameterBuilder.AppendFormat(" {0}", objCParamName.FirstCharacterToLower());
                    }
                    ObjCParameterBuilder.AppendFormat(":({0})p{1}", objCParamTypeDecl, idx + 1);

                    //
                    // build the mono invocation argument representation
                    // eg: DB_VALUE(p1), DB_VALUE(p2), [p3 monoRTInvokeArg]
                    //
                    string argFormat = null;
                    if (idx > 0)
                    {
                        InvokeArgsBuilder.Append(", ");
                    }
                    if (objCParameterIsObject)
                    {
                        if (parameter.IsByRef)
                        {
                            argFormat = "&refPtr{0}";                               // use reference pointer
                        }
                        else
                        {
                            argFormat = "[p{0} monoRTInvokeArg]";
                        }
                    }
                    else
                    {
                        if (parameter.IsByRef || parameter.IsPointer)
                        {
                            argFormat = "p{0}";                             // just pass the pointer
                        }
                        else
                        {
                            argFormat = "DB_VALUE(p{0})";                               // DB_VALUE equates to &
                        }
                    }
                    InvokeArgsBuilder.AppendFormat(argFormat, idx + 1);

                    //
                    // Build reference parameter pre and post process assignment statements
                    //
                    // Reference parameters need to be assigned to temporary variables
                    // to allow for their mutation
                    //
                    if (objCParameterIsObject && parameter.IsByRef)
                    {
                        // dereference and assign temporary variable
                        string preProcess = string.Format("void *refPtr{0} = [*p{0} monoRTInvokeArg];{1}", idx + 1, Environment.NewLine);
                        ReferencePreProcessBuilder.Append(preProcess);

                        // create new object subclass for reference
                        string postProcess = string.Format("*p{0} = [System_Object bestObjectWithMonoObject:refPtr{0}];{1}", idx + 1, Environment.NewLine);
                        ReferencePostProcessBuilder.Append(postProcess);
                    }

                    idx++;
                }
            }
Пример #7
0
            public Method(Net2ObjC n2c, MethodFacet facet, Dictionary <string, object> options = null)
            {
                // In order to ensure compilation of an assembly and its references
                // the generated code must resolve all types.
                //
                // The generation of a complete set of methods is obviously desirable
                // but in some cases may not be achievable if a unique method signature
                // cannot be obtained.

                // if the method is a duplicate (ie: name, parameter types, return type)
                // then we have no option but to omit it
                if (facet.IsDuplicateSignatureMethod)
                {
                    n2c.Warning("Duplicate method omitted : " + facet.Name);
                    return;
                }

                // if the facet is overloaded on its signature and differs only in its
                // return type then omit it.
                // This can occur with explicit operators.
                // At present it is unknown if these can be called via the embedded API.
                if (facet.IsOverloadedSignatureMethod)
                {
                    n2c.Warning("Overloaded signature method omitted : " + facet.Name);
                    return;
                }

                string objCMethodInvokeFormat  = null;
                string objCMethodPrepareFormat = null;

                IsConstructorMethod = (facet.Name == null);                    // constructor has no method name
                ObjCMethodType      = null;

                // Method name. We do some rudimentary processing to prevent troublesome behaviour.
                // We may have to prefix certain method names to conform to ARC's semantics
                // see https://stackoverflow.com/questions/22529454/simple-rules-for-naming-methods-compatible-with-arc-naming-conventions
                MonoMethodName = facet.Name;
                ObjCMethodName = MonoMethodName.FirstCharacterToLower();
                if (facet.IsStatic || IsConstructorMethod)
                {
                    ObjCMethodType = "+";
                    if (facet.Parameters.Count == 0)
                    {
                        // decorate class method names known to be unsafe
                        if (n2c.UnsafeObjCClassMethodNames().Contains(ObjCMethodName))
                        {
                            ObjCMethodName += "_";
                        }
                    }
                }
                else
                {
                    ObjCMethodType = "-";

                    // decorate instance method names known to be unsafe
                    if (facet.Type != "System.Void" && n2c.UnsafeObjCMethodNames().Any(p => ObjCMethodName.StartsWith(p, false, null)))
                    {
                        ObjCMethodName = "db_" + ObjCMethodName;
                    }
                }

                // Get ObjC declaration for method return type.
                // In general we want to allow the type association mechanism to substitute
                // native objC types for managed types where appropriate.
                // For example: a managed method that returns a System_DateTime results in an native method that returns an NSDate *.
                // However, when defining a constructor we don't want to permit this association to occur as the constructor
                // won't then contruct a managed instance at all.
                ObjCTypeDecl = n2c.ObjCTypeDeclFromManagedFacet(facet, !IsConstructorMethod);
                if (facet.IsInterface)
                {
                    ObjCTypeDecl = n2c.ObjCConformingTypeFromObjCTypeDecl(ObjCTypeDecl, true);
                }

                ManagedValueToObjC = null;

                // instance method requires a name and type
                if (!IsConstructorMethod)
                {
                    // create Obj-C representation of mono object
                    ManagedValueToObjC = n2c.ManagedValueToObjc(ManagedVariableName, facet);

                    if (!facet.IsStatic)
                    {
                        if (!facet.IsGenericMethodDefinition)
                        {
                            objCMethodInvokeFormat = "[self invokeMonoMethod:\"{0}({1})\" withNumArgs:{2}]";
                        }
                        else
                        {
                            objCMethodPrepareFormat = "DBManagedMethod *managedMethod = [[DBGenericTypeHelper sharedHelper] methodWithMonoMethodNamed:\"{0}({1})\" typeParameters:typeParameter]";
                            objCMethodInvokeFormat  = "[self invokeMethod:managedMethod withNumArgs:{2}]";
                        }
                    }
                    else
                    {
                        objCMethodInvokeFormat = "[self invokeMonoClassMethod:\"{0}({1})\" withNumArgs:{2}]";
                    }
                }
                else
                {
                    // this looks like a default constructor
                    if (facet.Parameters.Count() == 0)
                    {
                        return;
                    }

                    ObjCMethodName = "new";

                    // a constructor requires no explicit name or type
                    objCMethodInvokeFormat = "[[self alloc] initWithSignature:\"{1}\" withNumArgs:{2}]";
                }

                // process the parameters
                ProcessParameters(n2c, facet, options);

                // a generic method definition will require an additional parameter to specify the generic type parameters
                if (facet.IsGenericMethodDefinition)
                {
                    // get number of generic type arameters defined by the generic method definition as opposed to by the type defining the method
                    int    numberOfTypeParametersDeclaredByMethod = facet.GenericMethodDefinitionGenericTypeArguments.Count();
                    string parameterSig = "typeParameter:(id)typeParameter";
                    if (numberOfTypeParametersDeclaredByMethod > 1)
                    {
                        parameterSig = "typeParameters:(NSArray<id> *)typeParameter";
                    }
                    if (facet.Parameters.Count() == 0)
                    {
                        ObjCMethodName += "_with";
                        ObjCParameterBuilder.AppendFormat("{0}", parameterSig.FirstCharacterToUpper());
                    }
                    else
                    {
                        ObjCParameterBuilder.AppendFormat(" {0}", parameterSig);
                    }
                }

                // finalize argument list representations
                string monoMethodSig = MonoSigBuilder.ToString();

                ObjCMethodParameters = ObjCParameterBuilder.ToString();
                string invokeArgs = facet.Parameters.Count().ToString();

                if (facet.Parameters.Count() > 0)
                {
                    invokeArgs += ", " + InvokeArgsBuilder.ToString();
                }

                // form mono method invocation name.
                // a prefix may be required, for instance when calling explicit interface methods.
                string monoMethodPrefix = "";

                if (options != null)
                {
                    if (options.ContainsKey("cAPIMethodPrefix"))
                    {
                        monoMethodPrefix = (string)options["cAPIMethodPrefix"];
                    }
                }
                string monoInvocationName = monoMethodPrefix + MonoMethodName;

                // we may have an expression that prepares the get expression method argument
                if (objCMethodPrepareFormat != null)
                {
                    string expression = String.Format(objCMethodPrepareFormat, monoInvocationName, monoMethodSig, invokeArgs) + ";";
                    ReferencePreProcessBuilder.AppendFormat("{0}{1}", expression, Environment.NewLine);
                }

                // the get expression invokes the method and gets the result
                GetExpression = String.Format(objCMethodInvokeFormat, monoInvocationName, monoMethodSig, invokeArgs);

                // validation
                if (IsConstructorMethod && String.IsNullOrEmpty(monoMethodSig))
                {
                    throw new Exception("Mono method argument signature is empty");
                }
                if (String.IsNullOrEmpty(ObjCTypeDecl))
                {
                    throw new Exception("ObjC type Declaration is empty");
                }
                if (String.IsNullOrEmpty(ObjCMethodName))
                {
                    throw new Exception("Method name is empty");
                }
                if (String.IsNullOrEmpty(GetExpression))
                {
                    throw new Exception("Get expression is empty");
                }

                IsValid = true;
            }