private static bool DefineResourceFetchingProperty(string propertyName, string resourceName,
			ResourceData resourceData, CodeTypeDeclaration resourceClass, bool internalClass, bool useStatic)
        {
            CodeMethodReturnStatement propertyReturnStatement;
            CodeMemberProperty resourceProperty = new CodeMemberProperty();
            resourceProperty.Name = propertyName;
            resourceProperty.HasGet = true;
            resourceProperty.HasSet = false;

            Type resourceDataType = resourceData.Type;
            if (null == resourceDataType)
                return false;

            if (typeof(MemoryStream) == resourceDataType)
                resourceDataType = typeof(UnmanagedMemoryStream);

            while (!resourceDataType.IsPublic)
                resourceDataType = resourceDataType.BaseType;

            CodeTypeReference resourceDataTypeReference = new CodeTypeReference(resourceDataType);
            resourceProperty.Type = resourceDataTypeReference;
            if (internalClass)
                resourceProperty.Attributes = MemberAttributes.Assembly;
            else
                resourceProperty.Attributes = MemberAttributes.Public;

            if (useStatic)
                resourceProperty.Attributes |= MemberAttributes.Static;

            CodePropertyReferenceExpression resMgrPropertyReferenceExpression = new CodePropertyReferenceExpression(null, ResMgrPropertyName);
            CodeFieldReferenceExpression cultureInfoFieldReference = new CodeFieldReferenceExpression(useStatic ? null : ((CodeExpression)new CodeThisReferenceExpression()), CultureInfoFieldName);
            bool stringResourceDataType = typeof(string) == resourceDataType;
            bool memoryStreamResourceDataType = (typeof(UnmanagedMemoryStream) == resourceDataType) ||
                (typeof(MemoryStream) == resourceDataType);
            string methodName = "GetObject";
            string codeCommentString = string.Format(CultureInfo.CurrentCulture, NonStringPropertyComment, resourceName);
            if (stringResourceDataType)
            {
                methodName = "GetString";
                string resourceStringValue = resourceData.ValueIfString;
                if (resourceStringValue.Length > DocCommentLengthThreshold)
                {
                    resourceStringValue = string.Format(CultureInfo.CurrentCulture, StringTruncatedComment,
                        resourceStringValue.Substring(0, DocCommentLengthThreshold));
                }

                resourceStringValue = SecurityElement.Escape(resourceStringValue);
                codeCommentString = string.Format(CultureInfo.CurrentCulture,
                    StringPropertyComment, resourceStringValue);
            }
            else if (memoryStreamResourceDataType)
                methodName = "GetStream";

            AddComments(resourceProperty, codeCommentString);

            CodeExpression resourceNameExpression = useStatic ?
                (CodeExpression)(new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(new CodeTypeReference(ResourceNamesNestedClassName)), propertyName)) :
                (CodeExpression)(new CodePrimitiveExpression(resourceName));

            CodeExpression invokeCodeExpression = new CodeMethodInvokeExpression(resMgrPropertyReferenceExpression, methodName,
                new CodeExpression[] { resourceNameExpression, cultureInfoFieldReference });
            if (stringResourceDataType || memoryStreamResourceDataType)
                propertyReturnStatement = new CodeMethodReturnStatement(invokeCodeExpression);
            else
                propertyReturnStatement = new CodeMethodReturnStatement(new CodeCastExpression(resourceDataTypeReference, invokeCodeExpression));

            resourceProperty.GetStatements.Add(propertyReturnStatement);

            resourceClass.Members.Add(resourceProperty);

            return true;
        }
        /// <summary>Generates a class file that contains strongly-typed properties that match the resources in the specified .resx file.</summary>
        /// <returns>A <see cref="T:System.CodeDom.CodeCompileUnit"></see> container.</returns>
        /// <param name="callerType">The type of the caller class.</param>
        /// <param name="baseName">The name of the class to be generated.</param>
        /// <param name="internalClass">true to generate an internal class; false to generate a public class.</param>
        /// <param name="resourcesNamespace">The namespace of the resource to be generated. </param>
        /// <param name="codeProvider">A <see cref="T:System.CodeDom.Compiler.CodeDomProvider"></see>  class that provides the language in which the class will be generated.</param>
        /// <param name="unmatchable">A list that contains each resource name for which a property cannot be generated. Typically, a property cannot be generated because the resource name is not a valid identifier.</param>
        /// <param name="generatedCodeNamespace">The namespace of the class to be generated.</param>
        /// <param name="resxFile">The name of a .resx file used as input.</param>
        /// <exception cref="T:System.ArgumentNullException">basename or codeProvider is null.</exception>
        public static CodeCompileUnit Create(Type callerType, string resxFile, string baseName, string generatedCodeNamespace,
			string resourcesNamespace, CodeDomProvider codeProvider, bool internalClass, List<ResourceErrorData> unmatchable)
        {
            if (null == resxFile)
                throw new ArgumentNullException("resxFile");

            Dictionary<string, ResourceData> resourceDataDictionary = new Dictionary<string, ResourceData>(StringComparer.InvariantCultureIgnoreCase);
            using (ResXResourceReader resXReader = new ResXResourceReader(resxFile))
            {
                resXReader.UseResXDataNodes = true;
                foreach (DictionaryEntry resourceEntry in resXReader)
                {
                    ResXDataNode resXNode = (ResXDataNode)resourceEntry.Value;

                    string valueTypeName = resXNode.GetValueTypeName((AssemblyName[])null);
                    Type valueType = Type.GetType(valueTypeName);

                    string valueText = null;
                    if (valueType == typeof(string))
                        valueText = (string)resXNode.GetValue((AssemblyName[])null);

                    ResourceData resourceData = new ResourceData(valueType, valueText);
                    resourceDataDictionary.Add((string)resourceEntry.Key, resourceData);
                }
            }

            return InternalCreate(callerType, resourceDataDictionary, baseName, generatedCodeNamespace, resourcesNamespace,
                codeProvider, internalClass, unmatchable);
        }
        private static void DefineFormattedResourceFetchingMethod(string methodName, string propertyName,
			string resourceName, ResourceData resourceData, CodeTypeDeclaration resourceClass,
			bool internalClass, bool useStatic, int numberOfArguments)
        {
            Type stringType = resourceData.Type;
            Type objectType = typeof(object);
            CodeMethodReturnStatement methodReturnStatement;
            CodeMemberMethod resourceFormatMethod = new CodeMemberMethod();
            resourceFormatMethod.Name = methodName;

            for (int index = 0; index < numberOfArguments; ++index)
            {
                CodeParameterDeclarationExpression parameterDeclarationExpression =
                    new CodeParameterDeclarationExpression(objectType, "arg" + index.ToString(CultureInfo.InvariantCulture));
                resourceFormatMethod.Parameters.Add(parameterDeclarationExpression);
            }

            // Prevent the code analysis error indicating to use a param array
            if (numberOfArguments > 3)
            {
                CodeAttributeDeclaration suppressAttributeDeclaration = new CodeAttributeDeclaration(new CodeTypeReference(typeof(SuppressMessageAttribute)));
                suppressAttributeDeclaration.AttributeType.Options = CodeTypeReferenceOptions.GlobalReference;
                suppressAttributeDeclaration.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression("Microsoft.Design")));
                suppressAttributeDeclaration.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression("CA1025:ReplaceRepetitiveArgumentsWithParamsArray")));
                resourceFormatMethod.CustomAttributes.Add(suppressAttributeDeclaration);

            }

            CodeTypeReference stringTypeReference = new CodeTypeReference(stringType);
            resourceFormatMethod.ReturnType = stringTypeReference;
            if (internalClass)
                resourceFormatMethod.Attributes = MemberAttributes.Assembly;
            else
                resourceFormatMethod.Attributes = MemberAttributes.Public;

            if (useStatic)
                resourceFormatMethod.Attributes |= MemberAttributes.Static;

            string resourceStringValue = resourceData.ValueIfString;
            if (resourceStringValue.Length > DocCommentLengthThreshold)
            {
                resourceStringValue = string.Format(CultureInfo.CurrentCulture, StringTruncatedComment,
                    resourceStringValue.Substring(0, DocCommentLengthThreshold));
            }
            resourceStringValue = SecurityElement.Escape(resourceStringValue);
            string codeCommentString = numberOfArguments > 0 ? string.Format(CultureInfo.CurrentCulture,
                FormatMethodComment, resourceStringValue) : string.Format(CultureInfo.CurrentCulture,
                FormatStubMethodComment, propertyName);
            AddComments(resourceFormatMethod, codeCommentString);

            for (int index = 0; index < numberOfArguments; ++index)
            {
                resourceFormatMethod.Comments.Add(new CodeCommentStatement(string.Format(CultureInfo.InvariantCulture,
                    ParamCommentStatement, index), true));
            }

            string returnValueCommentString = numberOfArguments > 0 ? MethodReturnValueComment :
                string.Format(StubMethodReturnValueComment, propertyName);
            resourceFormatMethod.Comments.Add(new CodeCommentStatement(returnValueCommentString, true));

            CodePropertyReferenceExpression resPropertyReferenceExpression = new CodePropertyReferenceExpression(null, propertyName);

            if (numberOfArguments > 0)
            {
                CodeFieldReferenceExpression cultureInfoFieldReference = new CodeFieldReferenceExpression(useStatic ? null : ((CodeExpression)new CodeThisReferenceExpression()),
                    CultureInfoFieldName);
                CodeTypeReferenceExpression stringTypeReferenceExpression = new CodeTypeReferenceExpression(stringTypeReference);
                CodeMethodReferenceExpression stringFormatMethodReference = new CodeMethodReferenceExpression(stringTypeReferenceExpression,
                    "Format");
                CodeExpression[] formatExpressionParameters = new CodeExpression[2 + numberOfArguments];
                formatExpressionParameters[0] = cultureInfoFieldReference;
                formatExpressionParameters[1] = resPropertyReferenceExpression;
                for (int index = 0; index < numberOfArguments; ++index)
                {
                    CodeVariableReferenceExpression parameterReference = new CodeVariableReferenceExpression("arg" +
                        index.ToString(CultureInfo.InvariantCulture));
                    formatExpressionParameters[2 + index] = parameterReference;
                }
                CodeExpression stringFormatExpression = new CodeMethodInvokeExpression(stringFormatMethodReference,
                    formatExpressionParameters);

                methodReturnStatement = new CodeMethodReturnStatement(stringFormatExpression);
            }
            else
                methodReturnStatement = new CodeMethodReturnStatement(resPropertyReferenceExpression);

            resourceFormatMethod.Statements.Add(methodReturnStatement);

            resourceClass.Members.Add(resourceFormatMethod);
        }
        /// <summary>Generates a class file that contains strongly-typed properties that match the resources referenced in the specified collection.</summary>
        /// <returns>A <see cref="T:System.CodeDom.CodeCompileUnit"></see> container.</returns>
        /// <param name="callerType">The type of the caller class.</param>
        /// <param name="baseName">The name of the class to be generated.</param>
        /// <param name="internalClass">true to generate an internal class; false to generate a public class.</param>
        /// <param name="resourcesNamespace">The namespace of the resource to be generated. </param>
        /// <param name="generatedCodeNamespace">The namespace of the class to be generated.</param>
        /// <param name="codeProvider">A <see cref="T:System.CodeDom.Compiler.CodeDomProvider"></see> object that provides the language in which the class will be generated.</param>
        /// <param name="resourceList">An <see cref="T:System.Collections.IDictionary"></see> collection where each dictionary entry key/value pair is the name of a resource and the value of the resource.</param>
        /// <param name="unmatchable">A list that contains each resource name for which a property cannot be generated. Typically, a property cannot be generated because the resource name is not a valid identifier.</param>
        /// <exception cref="T:System.ArgumentNullException">resourceList, basename, or codeProvider is null.</exception>
        public static CodeCompileUnit Create(Type callerType, IDictionary resourceList, string baseName,
			string generatedCodeNamespace, string resourcesNamespace, CodeDomProvider codeProvider,
			bool internalClass, List<ResourceErrorData> unmatchable)
        {
            if (null == resourceList)
                throw new ArgumentNullException("resourceList");

            Dictionary<string, ResourceData> resourceDataDictionary = new Dictionary<string, ResourceData>(StringComparer.InvariantCultureIgnoreCase);
            foreach (DictionaryEntry resourceEntry in resourceList)
            {
                ResourceData resourceData;
                ResXDataNode resXNode = resourceEntry.Value as ResXDataNode;
                if (null != resXNode)
                {
                    string resourceName = (string)resourceEntry.Key;
                    if (resourceName != resXNode.Name)
                        throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MismatchedResourceName,
                            resourceName, resXNode.Name));

                    string valueTypeName = resXNode.GetValueTypeName((AssemblyName[])null);
                    Type valueType = Type.GetType(valueTypeName);

                    string valueText = null;
                    if (valueType == typeof(string))
                        valueText = (string)resXNode.GetValue((AssemblyName[])null);

                    resourceData = new ResourceData(valueType, valueText);
                }
                else
                {
                    Type valueType = (null == resourceEntry.Value) ? typeof(object) : resourceEntry.Value.GetType();
                    resourceData = new ResourceData(valueType, resourceEntry.Value as string);
                }

                resourceDataDictionary.Add((string)resourceEntry.Key, resourceData);
            }

            return InternalCreate(callerType, resourceDataDictionary, baseName, generatedCodeNamespace,
                resourcesNamespace, codeProvider, internalClass, unmatchable);
        }