示例#1
0
        /// <summary>
        /// Get custom property name if decorated by DataMemberAttribute or JsonPropertyAttribute. If not defined, return null.
        /// </summary>
        /// <param name="memberInfo"></param>
        /// <param name="methods"></param>
        /// <returns></returns>
        public static string GetFieldCustomName(MemberInfo memberInfo, CherryPickingMethods methods)
        {
            //opt-in for DataContract through DataMemberAttribute , and the type may or may not be decorated by DataContractAttribute.
            // Enum will have all member fields being picked, regardless of the EnumMemberAttribute.
            if ((methods & CherryPickingMethods.DataContract) == CherryPickingMethods.DataContract)
            {
                var a = TypeHelper.ReadAttribute <DataMemberAttribute>(memberInfo);
                if (a != null)
                {
                    return(a.Name);
                }
            }

            //opt-in for NewtonsoftJson through JsonPropertyAttribute,  , and the type may or may not be decorated by JsonObjectAttribute.
            if ((methods & CherryPickingMethods.NewtonsoftJson) == CherryPickingMethods.NewtonsoftJson)
            {
                //       var a =TypeHelper.AttributeExists(memberInfo, "Newtonsoft.Json.JsonIgnoreAttribute");
                var a = TypeHelper.ReadAttribute <Newtonsoft.Json.JsonIgnoreAttribute>(memberInfo);
                if (a == null)
                {
                    var njAttribute = TypeHelper.ReadAttribute <Newtonsoft.Json.JsonPropertyAttribute>(memberInfo);
                    if (njAttribute != null && !String.IsNullOrEmpty(njAttribute.PropertyName))
                    {
                        return(njAttribute.PropertyName);
                    }
                }
            }

            return(null);
        }
示例#2
0
        public void CreateCodeDom(Assembly assembly, CherryPickingMethods methods, DocCommentLookup docLookup)
        {
            this.docLookup = docLookup;
            var cherryTypes = PodGenHelper.GetCherryTypes(assembly, methods);

            CreateCodeDom(cherryTypes, methods);
        }
示例#3
0
        public static bool IsCherryType(Type type, CherryPickingMethods methods)
        {
            bool r0, r1, r2, r3, r4;

            r0 = r1 = r2 = r3 = r4 = false;

            if ((methods & CherryPickingMethods.DataContract) == CherryPickingMethods.DataContract)
            {
                r1 = TypeHelper.ReadAttribute <DataContractAttribute>(type) != null;
            }

            if ((methods & CherryPickingMethods.NewtonsoftJson) == CherryPickingMethods.NewtonsoftJson)
            {
                r2 = TypeHelper.AttributeExists(type, "Newtonsoft.Json.JsonObjectAttribute") != null;
            }

            if ((methods & CherryPickingMethods.Serializable) == CherryPickingMethods.Serializable)
            {
                r3 = TypeHelper.ReadAttribute <SerializableAttribute>(type) != null;
            }

            if ((methods & CherryPickingMethods.AspNet) == CherryPickingMethods.AspNet)//Asp.net does not seem to define good data annotation for cherry picking types
            {
                r4 = true;
            }

            if (methods == CherryPickingMethods.All)
            {
                r0 = true;
            }

            return(r0 | r1 | r2 | r3 | r4);
        }
示例#4
0
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.WriteLine("Poco2Ts.exe generates TypeScript data model interfaces from POCO classes.");
                Console.WriteLine(@"Example:  
For classes decorated by DataContractAttribute:
  Fonlow.Poco2Ts.exe MyAssemblyWithPOCO.dll MyOutputTS.ts
For classes decorated by Newtonsoft.Json.JsonObjectAttribute:
  Fonlow.Poco2Ts.exe MyAssemblyWithPOCO.dll MyOutputTS.ts /2
For classes decorated by SerializableAttribute:
  Fonlow.Poco2Ts.exe MyAssemblyWithPOCO.dll MyOutputTS.ts /4
For public classes, properties and properties, and use System.ComponentModel.DataAnnotations.RequiredAttribute:
  Fonlow.Poco2Ts.exe MyAssemblyWithPOCO.dll MyOutputTS.ts /8
For all classes, properties and fields
  Fonlow.Poco2Ts.exe MyAssemblyWithPOCO.dll MyOutputTS.ts /0

");
                return;
            }

            var assemblyName             = args[0];
            var tsFileName               = args[1];
            CherryPickingMethods methods = CherryPickingMethods.DataContract;

            if (args.Length > 2)
            {
                methods = ReadMethods(args[2]);
            }
            AppDomain appDomain = AppDomain.CurrentDomain;

            appDomain.AssemblyResolve += AppDomain_AssemblyResolve;
            Fonlow.TypeScriptCodeDom.TsCodeGenerationOptions.Instance.CamelCase = true;
            PocoAssemblyFileWalker.Walk(assemblyName, tsFileName, methods, ".Client", true);
        }
示例#5
0
        public void CreateCodeDom(Assembly assembly, CherryPickingMethods methods, DocCommentLookup docLookup, ModelGenOutputs codeGenOutputs)
        {
            this.docLookup = docLookup;
            this.settings  = codeGenOutputs;
            var cherryTypes = PodGenHelper.GetCherryTypes(assembly, methods);

            CreateCodeDom(cherryTypes, methods, settings.CSClientNamespaceSuffix);
        }
示例#6
0
        public void CreateCodeDom(Assembly assembly, CherryPickingMethods methods, DocCommentLookup docLookup, string clientNamespaceSuffix)
        {
            this.docLookup             = docLookup;
            this.clientNamespaceSuffix = clientNamespaceSuffix;
            var cherryTypes = PodGenHelper.GetCherryTypes(assembly, methods);

            CreateCodeDom(cherryTypes, methods, clientNamespaceSuffix);
        }
示例#7
0
        public void CreateCodeDom(Assembly assembly, CherryPickingMethods methods, DocCommentLookup docLookup, string clientNamespaceSuffix, bool dataAnnotationsEnabled, bool dataAnnotationsToComments)
        {
            this.docLookup                 = docLookup;
            this.clientNamespaceSuffix     = clientNamespaceSuffix;
            this.dataAnnotationsEnabled    = dataAnnotationsEnabled;
            this.dataAnnotationsToComments = dataAnnotationsToComments;
            var cherryTypes = PodGenHelper.GetCherryTypes(assembly, methods);

            CreateCodeDom(cherryTypes, methods, clientNamespaceSuffix);
        }
示例#8
0
        /// <summary>
        /// Walk classes in the assembly decorated by cherry picking data annotation attributes, and save TypeScript codes to the file.
        /// </summary>
        /// <param name="assemblyFilePath">Absolute or relative path, including the assembly file extension name dll or exe.</param>
        /// <param name="tsFilePath"></param>
        /// <param name="methods"></param>
        public static void Walk(string assemblyFilePath, string tsFilePath, CherryPickingMethods methods, string clientNamespaceSuffix)
        {
            var absolutePath = System.IO.Path.GetFullPath(assemblyFilePath);
            var assembly     = LoadAssembly(absolutePath);

            if (assembly == null)
            {
                return;
            }

            var lookup = Fonlow.DocComment.DocCommentLookup.Create(DocComment.DocCommentLookup.GetXmlPath(assembly));
            var gen    = new Poco2TsGen();

            gen.CreateCodeDom(assembly, methods, lookup, clientNamespaceSuffix);
            gen.SaveCodeToFile(tsFilePath);
            var msg = $"{tsFilePath} is generated.";

            Console.WriteLine(msg);
            Trace.WriteLine(msg);
        }
示例#9
0
        internal static Type[] GetCherryTypes(Assembly assembly, CherryPickingMethods methods)
        {
            try
            {
                return(assembly.GetTypes().Where(type => (TypeHelper.IsClassOrStruct(type) || type.IsEnum) &&
                                                 CherryPicking.IsCherryType(type, methods)).ToArray());
            }
            catch (ReflectionTypeLoadException e)
            {
                foreach (Exception ex in e.LoaderExceptions)
                {
                    Trace.TraceWarning(String.Format("When loading {0}, GetTypes errors occur: {1}", assembly.FullName, ex.Message));
                }
            }
            catch (TargetInvocationException e)
            {
                Trace.TraceWarning(String.Format("When loading {0}, GetTypes errors occur: {1}", assembly.FullName, e.Message + "~~" + e.InnerException.Message));
            }

            return(null);
        }
示例#10
0
        /// <summary>
        /// Create TypeScript CodeDOM for POCO types.
        /// For an enum type, all members will be processed regardless of EnumMemberAttribute.
        /// </summary>
        /// <param name="types">POCO types.</param>
        /// <param name="methods">How to cherry pick data to be exposed to the clients.</param>
        /// <param name="clientNamespaceSuffix"></param>
        public void CreateCodeDom(Type[] types, CherryPickingMethods methods, string clientNamespaceSuffix)
        {
            if (types == null)
            {
                throw new ArgumentNullException(nameof(types), "types is not defined.");
            }

            this.pendingTypes.AddRange(types);

            var typeGroupedByNamespace = types
                                         .GroupBy(d => d.Namespace)
                                         .OrderBy(k => k.Key); // order by namespace
            var namespacesOfTypes = typeGroupedByNamespace.Select(d => d.Key).ToArray();

            foreach (var groupedTypes in typeGroupedByNamespace)
            {
                var clientNamespaceText = (groupedTypes.Key + clientNamespaceSuffix);
                var clientNamespace     = new CodeNamespace(clientNamespaceText);
                codeCompileUnit.Namespaces.Add(clientNamespace);                //namespace added to Dom

                Debug.WriteLine("Generating types in namespace: " + groupedTypes.Key + " ...");
                groupedTypes.OrderBy(t => t.Name).Select(type =>
                {
                    var tsName = type.Name;
                    Debug.WriteLine("clientClass: " + clientNamespace + "  " + tsName);

                    CodeTypeDeclaration typeDeclaration;
                    if (TypeHelper.IsClassOrStruct(type))
                    {
                        if (type.IsGenericType)
                        {
                            typeDeclaration = PodGenHelper.CreatePodClientGenericClass(clientNamespace, type);
                        }
                        else
                        {
                            typeDeclaration = type.IsClass ? PodGenHelper.CreatePodClientClass(clientNamespace, tsName) : PodGenHelper.CreatePodClientStruct(clientNamespace, tsName);
                        }

                        if (!type.IsValueType)
                        {
                            if (namespacesOfTypes.Contains(type.BaseType.Namespace))
                            {
                                typeDeclaration.BaseTypes.Add(RefineCustomComplexTypeText(type.BaseType));
                            }
                            else
                            {
                                typeDeclaration.BaseTypes.Add(type.BaseType);
                            }
                        }

                        CreateTypeDocComment(type, typeDeclaration);

                        var typeCherryMethods = CherryPicking.GetTypeCherryMethods(type);
                        bool withDataContract = (typeCherryMethods & CherryPickingMethods.DataContract) == CherryPickingMethods.DataContract;
                        var typeProperties    = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public).OrderBy(p => p.Name).ToArray();
                        foreach (var propertyInfo in typeProperties)
                        {
                            var cherryType = CherryPicking.GetMemberCherryType(propertyInfo, methods, withDataContract);
                            if (cherryType == CherryType.None)
                            {
                                continue;
                            }
                            string tsPropertyName;


                            //todo: Maybe the required of JsonMemberAttribute?       var isRequired = cherryType == CherryType.BigCherry;
                            tsPropertyName = propertyInfo.Name;                            //todo: String.IsNullOrEmpty(dataMemberAttribute.Name) ? propertyInfo.Name : dataMemberAttribute.Name;
                            Debug.WriteLine(String.Format("{0} : {1}", tsPropertyName, propertyInfo.PropertyType.Name));
                            var defaultValue = GetDefaultValue(propertyInfo.GetCustomAttribute(typeOfDefaultValueAttribute) as DefaultValueAttribute);

                            //var clientProperty = new CodeMemberProperty() //orthodox way of creating property, but resulting in verbose generated codes
                            //{
                            // Name = tsPropertyName,
                            // Type = TranslateToClientTypeReference(propertyInfo.PropertyType),
                            // Attributes = MemberAttributes.Public | MemberAttributes.Final,
                            //};
                            var clientProperty = CreateProperty(tsPropertyName, propertyInfo.PropertyType, defaultValue);                             //hacky way of creating clean getter and writter.

                            var isRequired = cherryType == CherryType.BigCherry;
                            if (isRequired)
                            {
                                clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.ComponentModel.DataAnnotations.RequiredAttribute"));
                            }

                            //var privateFieldName = "_" + tsPropertyName;

                            //typeDeclaration.Members.Add(new CodeMemberField()
                            //{
                            // Name = privateFieldName,
                            // Type = TranslateToClientTypeReference(propertyInfo.PropertyType),
                            //});

                            //clientProperty.GetStatements.Add(new CodeSnippetStatement($"\t\t\t\treturn {privateFieldName};"));
                            //clientProperty.SetStatements.Add(new CodeSnippetStatement($"\t\t\t\t{privateFieldName} = value;"));

                            if (settings.DataAnnotationsEnabled)
                            {
                                AddValidationAttributes(propertyInfo, clientProperty, isRequired);
                            }

                            CreatePropertyDocComment(propertyInfo, clientProperty);

                            if (settings.DecorateDataModelWithDataContract)
                            {
                                clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataMember"));
                            }

                            typeDeclaration.Members.Add(clientProperty);
                        }

                        var typeFields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public).OrderBy(f => f.Name).ToArray();
                        foreach (var fieldInfo in typeFields)
                        {
                            var cherryType = CherryPicking.GetMemberCherryType(fieldInfo, methods, withDataContract);
                            if (cherryType == CherryType.None)
                            {
                                continue;
                            }
                            string tsPropertyName;


                            tsPropertyName = fieldInfo.Name;                            //todo: String.IsNullOrEmpty(dataMemberAttribute.Name) ? propertyInfo.Name : dataMemberAttribute.Name;
                            Debug.WriteLine(String.Format("{0} : {1}", tsPropertyName, fieldInfo.FieldType.Name));
                            var defaultValue = GetDefaultValue(fieldInfo.GetCustomAttribute(typeOfDefaultValueAttribute) as DefaultValueAttribute);

                            //public fields of a class will be translated into properties
                            if (type.IsClass)
                            {
                                //var clientProperty = new CodeMemberProperty() //orthodox way of creating property, but resulting in verbose generated codes
                                //{
                                // Name = tsPropertyName,
                                // Type = TranslateToClientTypeReference(fieldInfo.FieldType),
                                // Attributes = MemberAttributes.Public | MemberAttributes.Final,
                                //};

                                var clientProperty = CreateProperty(tsPropertyName, fieldInfo.FieldType, defaultValue);                                 //hacky way of creating clean getter and writter.

                                var isRequired = cherryType == CherryType.BigCherry;
                                if (isRequired)
                                {
                                    clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.ComponentModel.DataAnnotations.RequiredAttribute"));
                                }

                                //var privateFieldName = "_" + tsPropertyName;

                                //typeDeclaration.Members.Add(new CodeMemberField()
                                //{
                                // Name = privateFieldName,
                                // Type = TranslateToClientTypeReference(fieldInfo.FieldType),
                                //});

                                //clientProperty.GetStatements.Add(new CodeSnippetStatement($"\t\t\t\treturn {privateFieldName};"));
                                //clientProperty.SetStatements.Add(new CodeSnippetStatement($"\t\t\t\t{privateFieldName} = value;"));

                                if (settings.DataAnnotationsEnabled)
                                {
                                    AddValidationAttributes(fieldInfo, clientProperty, isRequired);
                                }

                                CreateFieldDocComment(fieldInfo, clientProperty);

                                if (settings.DecorateDataModelWithDataContract)
                                {
                                    clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataMember"));
                                }

                                typeDeclaration.Members.Add(clientProperty);
                            }
                            else                             //public fields of struct
                            {
                                var clientField = new CodeMemberField()
                                {
                                    Name       = tsPropertyName,
                                    Type       = TranslateToClientTypeReference(fieldInfo.FieldType),
                                    Attributes = MemberAttributes.Public | MemberAttributes.Final,
                                    //todo: add some attributes
                                };

                                CreateFieldDocComment(fieldInfo, clientField);

                                if (settings.DecorateDataModelWithDataContract)
                                {
                                    clientField.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataMember"));
                                }

                                typeDeclaration.Members.Add(clientField);
                            }
                        }

                        if (settings.DecorateDataModelWithDataContract)
                        {
                            typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataContract", new CodeAttributeArgument("Namespace", new CodeSnippetExpression($"\"{settings.DataContractNamespace}\""))));
                        }

                        if (settings.DecorateDataModelWithSerializable)
                        {
                            typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.SerializableAttribute"));
                        }
                    }
                    else if (type.IsEnum)
                    {
                        typeDeclaration = PodGenHelper.CreatePodClientEnum(clientNamespace, tsName);

                        CreateTypeDocComment(type, typeDeclaration);

                        int k = 0;
                        foreach (var fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Static))                        //not to sort
                        {
                            var name     = fieldInfo.Name;
                            var intValue = (int)Convert.ChangeType(fieldInfo.GetValue(null), typeof(int));
                            Debug.WriteLine(name + " -- " + intValue);
                            var isInitialized = intValue != k;

                            var clientField = new CodeMemberField()
                            {
                                Name           = name,
                                Type           = new CodeTypeReference(fieldInfo.FieldType),
                                InitExpression = isInitialized ? new CodePrimitiveExpression(intValue) : null,
                            };

                            CreateFieldDocComment(fieldInfo, clientField);

                            if (settings.DecorateDataModelWithDataContract)
                            {
                                clientField.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.EnumMemberAttribute"));
                            }

                            typeDeclaration.Members.Add(clientField);
                            k++;
                        }

                        if (settings.DecorateDataModelWithDataContract)
                        {
                            typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataContract", new CodeAttributeArgument("Namespace", new CodeSnippetExpression($"\"{settings.DataContractNamespace}\""))));
                        }

                        if (settings.DecorateDataModelWithSerializable)
                        {
                            typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.SerializableAttribute"));
                        }
                    }
                    else
                    {
                        Trace.TraceWarning("Not yet supported: " + type.Name);
                        typeDeclaration = null;
                    }

                    return(typeDeclaration);
                }
                                                         ).ToArray();//add classes into the namespace
            }
        }
示例#11
0
        /// <summary>
        /// Create TypeScript CodeDOM for POCO types.
        /// For an enum type, all members will be processed regardless of EnumMemberAttribute.
        /// </summary>
        /// <param name="types">POCO types.</param>
        /// <param name="methods"></param>
        public void CreateCodeDom(Type[] types, CherryPickingMethods methods)
        {
            if (types == null)
            {
                throw new ArgumentNullException("types", "types is not defined.");
            }

            this.pendingTypes.AddRange(types);
            var typeGroupedByNamespace = types
                                         .GroupBy(d => d.Namespace)
                                         .OrderBy(k => k.Key); // order by namespace
            var namespacesOfTypes = typeGroupedByNamespace.Select(d => d.Key).ToArray();

            foreach (var groupedTypes in typeGroupedByNamespace)
            {
                var clientNamespaceText = (groupedTypes.Key + ".Client").Replace('.', '_');
                var clientNamespace     = new CodeNamespace(clientNamespaceText);
                targetUnit.Namespaces.Add(clientNamespace);                //namespace added to Dom

                Debug.WriteLine("Generating types in namespace: " + groupedTypes.Key + " ...");
                groupedTypes.OrderBy(t => t.Name).Select(type =>
                {
                    var tsName = type.Name;
                    Debug.WriteLine("tsClass: " + clientNamespace + "  " + tsName);

                    CodeTypeDeclaration typeDeclaration;
                    if (TypeHelper.IsClassOrStruct(type))
                    {
                        if (type.IsGenericType)
                        {
                            typeDeclaration = PodGenHelper.CreatePodClientGenericInterface(clientNamespace, type);
                        }
                        else
                        {
                            typeDeclaration = PodGenHelper.CreatePodClientInterface(clientNamespace, tsName);
                        }

                        if (!type.IsValueType)
                        {
                            if (namespacesOfTypes.Contains(type.BaseType.Namespace))
                            {
                                typeDeclaration.BaseTypes.Add(RefineCustomComplexTypeText(type.BaseType));
                            }
                            else
                            {
                                typeDeclaration.BaseTypes.Add(type.BaseType);
                            }
                        }

                        CreateTypeDocComment(type, typeDeclaration);

                        var typeProperties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public).OrderBy(p => p.Name).ToArray();
                        foreach (var propertyInfo in typeProperties)
                        {
                            var cherryType = CherryPicking.GetMemberCherryType(propertyInfo, methods);
                            if (cherryType == CherryType.None)
                            {
                                continue;
                            }
                            string tsPropertyName;


                            var isRequired = cherryType == CherryType.BigCherry;
                            var customName = CherryPicking.GetFieldCustomName(propertyInfo, methods);
                            if (String.IsNullOrEmpty(customName))
                            {
                                tsPropertyName = Fonlow.TypeScriptCodeDom.TsCodeGenerationOptions.Instance.CamelCase ? Fonlow.Text.StringExtensions.ToCamelCase(propertyInfo.Name) : propertyInfo.Name;
                            }
                            else
                            {
                                tsPropertyName = customName;
                            }

                            Debug.WriteLine(String.Format("{0} : {1}", tsPropertyName, propertyInfo.PropertyType.Name));
                            var clientField = new CodeMemberField()                            //Yes, clr property translated to ts field
                            {
                                Name = tsPropertyName + (isRequired ? String.Empty : "?"),
                                Type = TranslateToClientTypeReference(propertyInfo.PropertyType),
                                //                     Attributes = MemberAttributes.Public,
                            };

                            CreatePropertyDocComment(propertyInfo, clientField);

                            typeDeclaration.Members.Add(clientField);
                        }

                        var typeFields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public).OrderBy(f => f.Name).ToArray();
                        foreach (var fieldInfo in typeFields)
                        {
                            var cherryType = CherryPicking.GetMemberCherryType(fieldInfo, methods);
                            if (cherryType == CherryType.None)
                            {
                                continue;
                            }
                            string tsPropertyName;


                            var isRequired = (cherryType == CherryType.BigCherry) || !type.IsClass;                            //public fields in struct should all be value types, so required
                            var customName = CherryPicking.GetFieldCustomName(fieldInfo, methods);
                            if (String.IsNullOrEmpty(customName))
                            {
                                tsPropertyName = Fonlow.TypeScriptCodeDom.TsCodeGenerationOptions.Instance.CamelCase ? Fonlow.Text.StringExtensions.ToCamelCase(fieldInfo.Name) : fieldInfo.Name;
                            }
                            else
                            {
                                tsPropertyName = customName;
                            }

                            Debug.WriteLine(String.Format("{0} : {1}", tsPropertyName, fieldInfo.FieldType.Name));

                            var clientField = new CodeMemberField()
                            {
                                Name = tsPropertyName + (isRequired ? String.Empty : "?"),
                                Type = TranslateToClientTypeReference(fieldInfo.FieldType),
                            };

                            CreateFieldDocComment(fieldInfo, clientField);

                            typeDeclaration.Members.Add(clientField);
                        }
                    }
                    else if (type.IsEnum)
                    {
                        typeDeclaration = PodGenHelper.CreatePodClientEnum(clientNamespace, tsName);

                        CreateTypeDocComment(type, typeDeclaration);

                        int k = 0;
                        foreach (var fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Static))
                        {
                            var name     = fieldInfo.Name;
                            var intValue = (int)Convert.ChangeType(fieldInfo.GetValue(null), typeof(int));
                            Debug.WriteLine(name + " -- " + intValue);
                            var isInitialized = intValue != k;

                            var clientField = new CodeMemberField()
                            {
                                Name           = name,
                                Type           = new CodeTypeReference(fieldInfo.FieldType),
                                InitExpression = isInitialized ? new CodePrimitiveExpression(intValue) : null,
                            };

                            CreateFieldDocComment(fieldInfo, clientField);

                            typeDeclaration.Members.Add(clientField);
                            k++;
                        }
                    }
                    else
                    {
                        Trace.TraceWarning("Not yet supported: " + type.Name);
                        typeDeclaration = null;
                    }

                    return(typeDeclaration);
                }
                                                         ).ToArray();//add classes into the namespace
            }
        }
示例#12
0
        /// <summary>
        /// Create TypeScript CodeDOM for POCO types.
        /// For an enum type, all members will be processed regardless of EnumMemberAttribute.
        /// </summary>
        /// <param name="types">POCO types.</param>
        /// <param name="methods">How to cherry pick data to be exposed to the clients.</param>
        public void CreateCodeDom(Type[] types, CherryPickingMethods methods)
        {
            if (types == null)
            {
                throw new ArgumentNullException("types", "types is not defined.");
            }

            this.pendingTypes.AddRange(types);
            var typeGroupedByNamespace = types.GroupBy(d => d.Namespace);
            var namespacesOfTypes      = typeGroupedByNamespace.Select(d => d.Key).ToArray();

            foreach (var groupedTypes in typeGroupedByNamespace)
            {
                var clientNamespaceText = (groupedTypes.Key + ".Client");
                var clientNamespace     = new CodeNamespace(clientNamespaceText);
                targetUnit.Namespaces.Add(clientNamespace);//namespace added to Dom

                Debug.WriteLine("Generating types in namespace: " + groupedTypes.Key + " ...");
                groupedTypes.Select(type =>
                {
                    var tsName = type.Name;
                    Debug.WriteLine("clientClass: " + clientNamespace + "  " + tsName);

                    CodeTypeDeclaration typeDeclaration;
                    if (TypeHelper.IsClassOrStruct(type))
                    {
                        typeDeclaration = type.IsClass ? PodGenHelper.CreatePodClientClass(clientNamespace, tsName): PodGenHelper.CreatePodClientStruct(clientNamespace, tsName);

                        if (!type.IsValueType)
                        {
                            if (namespacesOfTypes.Contains(type.BaseType.Namespace))
                            {
                                typeDeclaration.BaseTypes.Add(RefineCustomComplexTypeText(type.BaseType));
                            }
                            else
                            {
                                typeDeclaration.BaseTypes.Add(type.BaseType);
                            }
                        }

                        CreateTypeDocComment(type, typeDeclaration);

                        foreach (var propertyInfo in type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public))
                        {
                            var cherryType = CherryPicking.GetMemberCherryType(propertyInfo, methods);
                            if (cherryType == CherryType.None)
                            {
                                continue;
                            }
                            string tsPropertyName;


                            //todo: Maybe the required of JsonMemberAttribute?       var isRequired = cherryType == CherryType.BigCherry;
                            tsPropertyName = propertyInfo.Name;//todo: String.IsNullOrEmpty(dataMemberAttribute.Name) ? propertyInfo.Name : dataMemberAttribute.Name;
                            Debug.WriteLine(String.Format("{0} : {1}", tsPropertyName, propertyInfo.PropertyType.Name));


                            var clientProperty = new CodeMemberProperty()
                            {
                                Name       = tsPropertyName,
                                Type       = TranslateToClientTypeReference(propertyInfo.PropertyType),
                                Attributes = MemberAttributes.Public | MemberAttributes.Final,
                                //todo: add some attributes
                            };

                            var isRequired = cherryType == CherryType.BigCherry;
                            if (isRequired)
                            {
                                clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.ComponentModel.DataAnnotations.RequiredAttribute"));
                            }

                            var privateFieldName = "_" + tsPropertyName;

                            typeDeclaration.Members.Add(new CodeMemberField()
                            {
                                Name = privateFieldName,
                                Type = TranslateToClientTypeReference(propertyInfo.PropertyType),
                            });

                            clientProperty.GetStatements.Add(new CodeSnippetStatement($"                return {privateFieldName};"));
                            clientProperty.SetStatements.Add(new CodeSnippetStatement($"                {privateFieldName} = value;"));

                            CreatePropertyDocComment(propertyInfo, clientProperty);

                            typeDeclaration.Members.Add(clientProperty);
                        }

                        foreach (var fieldInfo in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public))
                        {
                            var cherryType = CherryPicking.GetMemberCherryType(fieldInfo, methods);
                            if (cherryType == CherryType.None)
                            {
                                continue;
                            }
                            string tsPropertyName;


                            tsPropertyName = fieldInfo.Name;//todo: String.IsNullOrEmpty(dataMemberAttribute.Name) ? propertyInfo.Name : dataMemberAttribute.Name;
                            Debug.WriteLine(String.Format("{0} : {1}", tsPropertyName, fieldInfo.FieldType.Name));

                            //public fields of a class will be translated into properties
                            if (type.IsClass)
                            {
                                var clientProperty = new CodeMemberProperty()
                                {
                                    Name       = tsPropertyName,
                                    Type       = TranslateToClientTypeReference(fieldInfo.FieldType),
                                    Attributes = MemberAttributes.Public | MemberAttributes.Final,
                                    //todo: add some attributes
                                };

                                var isRequired = cherryType == CherryType.BigCherry;
                                if (isRequired)
                                {
                                    clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.ComponentModel.DataAnnotations.RequiredAttribute"));
                                }

                                var privateFieldName = "_" + tsPropertyName;

                                typeDeclaration.Members.Add(new CodeMemberField()
                                {
                                    Name = privateFieldName,
                                    Type = TranslateToClientTypeReference(fieldInfo.FieldType),
                                });

                                clientProperty.GetStatements.Add(new CodeSnippetStatement($"                return {privateFieldName};"));
                                clientProperty.SetStatements.Add(new CodeSnippetStatement($"                {privateFieldName} = value;"));

                                CreateFieldDocComment(fieldInfo, clientProperty);

                                typeDeclaration.Members.Add(clientProperty);
                            }
                            else //public fields of struct
                            {
                                var clientField = new CodeMemberField()
                                {
                                    Name       = tsPropertyName,
                                    Type       = TranslateToClientTypeReference(fieldInfo.FieldType),
                                    Attributes = MemberAttributes.Public | MemberAttributes.Final,
                                    //todo: add some attributes
                                };

                                CreateFieldDocComment(fieldInfo, clientField);

                                typeDeclaration.Members.Add(clientField);
                            }
                        }
                    }
                    else if (type.IsEnum)
                    {
                        typeDeclaration = PodGenHelper.CreatePodClientEnum(clientNamespace, tsName);

                        CreateTypeDocComment(type, typeDeclaration);

                        int k = 0;
                        foreach (var fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Static))
                        {
                            var name     = fieldInfo.Name;
                            var intValue = (int)Convert.ChangeType(fieldInfo.GetValue(null), typeof(int));
                            Debug.WriteLine(name + " -- " + intValue);
                            var isInitialized = intValue != k;

                            var clientField = new CodeMemberField()
                            {
                                Name           = name,
                                Type           = new CodeTypeReference(fieldInfo.FieldType),
                                InitExpression = isInitialized ? new CodePrimitiveExpression(intValue) : null,
                            };

                            CreateFieldDocComment(fieldInfo, clientField);

                            typeDeclaration.Members.Add(clientField);
                            k++;
                        }
                    }
                    else
                    {
                        Trace.TraceWarning("Not yet supported: " + type.Name);
                        typeDeclaration = null;
                    }

                    return(typeDeclaration);
                }
                                    ).ToArray();//add classes into the namespace
            }
        }
示例#13
0
        public static CherryType GetMemberCherryType(MemberInfo memberInfo, CherryPickingMethods methods, bool typeIsWithDataContract)
        {
            CherryType[] r = { CherryType.None, CherryType.None, CherryType.None, CherryType.None, CherryType.None };


            //opt-in for DataContract through DataMemberAttribute , and the type may or may not be decorated by DataContractAttribute.
            // Enum will have all member fields being picked, regardless of the EnumMemberAttribute.
            if ((methods & CherryPickingMethods.DataContract) == CherryPickingMethods.DataContract)
            {
                var a = TypeHelper.ReadAttribute <DataMemberAttribute>(memberInfo);
                if (a == null)
                {
                    r[1] = CherryType.None;
                }
                else
                {
                    r[1] = a.IsRequired ? CherryType.BigCherry : CherryType.Cherry;
                }

                if (typeIsWithDataContract)
                {
                    return(r[1]);
                }
            }

            //opt-in for NewtonsoftJson through JsonPropertyAttribute,  , and the type may or may not be decorated by JsonObjectAttribute.
            if ((methods & CherryPickingMethods.NewtonsoftJson) == CherryPickingMethods.NewtonsoftJson)
            {
                var a = TypeHelper.AttributeExists(memberInfo, "Newtonsoft.Json.JsonIgnoreAttribute");
                if (a == null)
                {
                    var a2 = TypeHelper.ReadAttribute <Newtonsoft.Json.JsonPropertyAttribute>(memberInfo);
                    if (a2 != null)
                    {
                        r[2] = TypeHelper.GetRequired(a2, "Required", "Default") ? CherryType.BigCherry : CherryType.Cherry;
                    }
                    else
                    {
                        r[2] = CherryType.Cherry;
                    }
                }
                else
                {
                    r[2] = CherryType.None;
                }
            }

            //opt-out for Serializable through NonSerializedAttribute
            if ((methods & CherryPickingMethods.Serializable) == CherryPickingMethods.Serializable)
            {
                var a = TypeHelper.ReadAttribute <NonSerializedAttribute>(memberInfo);
                if (a == null)
                {
                    var a2 = TypeHelper.ReadAttribute <RequiredAttribute>(memberInfo);
                    r[3] = a2 == null ? CherryType.Cherry : CherryType.BigCherry;
                }
                else
                {
                    r[3] = CherryType.None;
                }
            }

            //opt-out for AspNet
            if ((methods & CherryPickingMethods.AspNet) == CherryPickingMethods.AspNet)
            {
                var a = TypeHelper.ReadAttribute <RequiredAttribute>(memberInfo);
                r[4] = a == null ? CherryType.Cherry : CherryType.BigCherry;
            }

            //opt-out
            if (methods == CherryPickingMethods.All)
            {
                r[0] = CherryType.Cherry;
            }

            return(r.Max());
        }