コード例 #1
0
ファイル: DataHelper.cs プロジェクト: arcadeindy/CandyConquer
        /// <summary>
        /// Gets a compiler code based on a filler compile type.
        /// </summary>
        /// <param name="fillCompileType">The filler compile type.</param>
        /// <param name="filler">The filler.</param>
        /// <param name="fillType">The filler type.</param>
        /// <param name="formattedMembers">The formatted members.</param>
        /// <param name="namespaces">A collection of namespaces to format into the code.</param>
        /// <returns>A compilable string.</returns>
        internal static string GetCompilerCode <TFiller>(DataIgnoreType fillCompileType, TFiller filler, Type fillType, IEnumerable <string> formattedMembers, IEnumerable <string> namespaces)
            where TFiller : InternalDataFiller
        {
            var code = fillCompileType == DataIgnoreType.Read ?
                       DataCompiler.ReaderCode.Replace("@ReaderType", filler.ReaderName) :
                       DataCompiler.WriterCode;

            return(code.Replace("@Type", fillType.FullName.Replace("+", "."))
                   .Replace("@Members", string.Join("\r\n", formattedMembers))
                   .Replace("@Usings", string.Join("\r\n", namespaces)));
        }
コード例 #2
0
        /// <summary>
        /// Generates a fill method based on a model and a filler.
        /// </summary>
        /// <returns>A fill method.</returns>
        internal static MethodInfo GenerateFillMethod <TModel, TBaseModel, TFiller>(DataIgnoreType fillCompileType)
            where TBaseModel : DataModel <TModel, TBaseModel, TFiller>
            where TFiller : InternalDataFiller
        {
            var fillType = typeof(TModel);

            MethodInfo fillerMethod;

            if (fillCompileType == DataIgnoreType.Read)
            {
                if (_fillerReadMethods.TryGetValue(fillType.FullName, out fillerMethod))
                {
                    return(fillerMethod);
                }
            }
            else             // (implicit) if (fillCompileType == DataIgnoreType.Write)
            {
                if (_fillerWriteMethods.TryGetValue(fillType.FullName, out fillerMethod))
                {
                    return(fillerMethod);
                }
            }

            TFiller filler;

            if (!TryGetFiller <TFiller>(out filler))
            {
                throw new MemberAccessException("Cannot access the filler context. Make sure the filler has an instance.");
            }

            var members          = filler.CreateReadFormatInternal(DataHelper.GetPropertiesByIgnore <TModel, TBaseModel, TFiller>(null, fillCompileType));
            var namespaces       = new List <string>();
            var formattedMembers = members.Select(member => DataHelper.FormatMember(member, fillCompileType, namespaces));

            namespaces = namespaces.Distinct().ToList();

            var code = DataHelper.GetCompilerCode(fillCompileType, filler, fillType, formattedMembers, namespaces);

            return(CompileFillMethod(code, fillType, fillCompileType));
        }
コード例 #3
0
        /// <summary>
        /// Compiles the fill method based on generated code and a fill type.
        /// </summary>
        /// <param name="code">The generated code to compile.</param>
        /// <param name="fillType">The associated fill type.</param>
        /// <returns>The compiled fill method.</returns>
        private static MethodInfo CompileFillMethod(string code, Type fillType, DataIgnoreType fillCompilerType)
        {
            var compilerResults = DataCompiler.Compile <CSharpCodeProvider>(code);

            if (compilerResults.Errors.HasErrors)
            {
                Console.WriteLine(code);
                var errors = new List <string>();
                foreach (var error in compilerResults.Errors)
                {
                    errors.Add(error.ToString());
                }
                throw new DataCompilerException("Failed to compile ...", errors);
            }
            else
            {
                var method = DataCompiler.FindMethod(compilerResults.CompiledAssembly,
                                                     DataCompiler.Namespace,
                                                     fillCompilerType == DataIgnoreType.Read ? DataCompiler.ReaderClassName : DataCompiler.WriterClassName,
                                                     fillCompilerType == DataIgnoreType.Read ? DataCompiler.ReadMethod : DataCompiler.WriteMethod);

                if (method != null)
                {
                    if (fillCompilerType == DataIgnoreType.Read)
                    {
                        _fillerReadMethods.TryAdd(fillType.FullName, method);
                    }
                    else                     // (implicit) if (fillCompilerType == DataIgnoreType.Write)
                    {
                        _fillerWriteMethods.TryAdd(fillType.FullName, method);
                    }
                }

                return(method);
            }
        }
コード例 #4
0
ファイル: DataFiller.cs プロジェクト: arcadeindy/CandyConquer
 /// <summary>
 /// Generates a fill method internally.
 /// </summary>
 /// <returns>The generated fill method.</returns>
 internal MethodInfo GenerateFillMethodInternal <TModel, TBaseModel, TFiller>(DataIgnoreType fillCompileType)
     where TBaseModel : DataModel <TModel, TBaseModel, TFiller>
     where TFiller : InternalDataFiller
 {
     return(DataFillGenerator.GenerateFillMethod <TModel, TBaseModel, TFiller>(fillCompileType));
 }
コード例 #5
0
ファイル: DataHelper.cs プロジェクト: arcadeindy/CandyConquer
        /// <summary>
        /// Gets all properties by a specific ignore type.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="handleType">The type to handle. (Not ignore.)</param>
        /// <returns>An IEnumerable of PropertyInfo which is the properties.</returns>
        public static IEnumerable <PropertyInfo> GetPropertiesByIgnore <TModel, TBaseModel, TFiller>(TBaseModel model, DataIgnoreType handleType)
            where TBaseModel : DataModel <TModel, TBaseModel, TFiller>
            where TFiller : InternalDataFiller
        {
            if (model != null)
            {
                switch (handleType)
                {
                case DataIgnoreType.Read:
                    if (model.ReadMembers != null)
                    {
                        return(model.ReadMembers);
                    }
                    break;

                case DataIgnoreType.Write:
                    if (model.WriteMembers != null)
                    {
                        return(model.WriteMembers);
                    }
                    break;

                default:
                    throw new ArgumentException("handleType");
                }
            }

            var properties = typeof(TModel).GetProperties().Where(property =>
            {
                var ignoreAttribute = property.GetCustomAttribute <DataIgnoreAttribute>();
                return(ignoreAttribute == null || (ignoreAttribute.IgnoreType != handleType && ignoreAttribute.IgnoreType != DataIgnoreType.Both));
            }).ToList();

            if (model != null)
            {
                switch (handleType)
                {
                case DataIgnoreType.Read:
                    model.ReadMembers = properties;
                    break;

                case DataIgnoreType.Write:
                    model.WriteMembers = properties;
                    break;

                default:
                    throw new ArgumentException("handleType");
                }
            }

            return(properties);
        }
コード例 #6
0
ファイル: DataHelper.cs プロジェクト: arcadeindy/CandyConquer
        /// <summary>
        /// Formats a DataReadInfo member into a compilable string.
        /// </summary>
        /// <param name="member">The member.</param>
        /// <param name="fillCompileType">The filler compile type.</param>
        /// <param name="namespaces">A collection of namespaces where custom namespaces are added.</param>
        /// <returns>A string that's compilable.</returns>
        internal static string FormatMember(DataReadInfo member, DataIgnoreType fillCompileType, ICollection <string> namespaces)
        {
            // Reader ...///
            const string READ_FORMAT       = "reader.Get<{0}>(\"{1}\")";
            const string SET_CUSTOM_FORMAT = "model.{0} = {1};";
            const string SET_FORMAT        = "model.{0} = ({1}){2};";

            // Writer ...
            const string WRITE_FORMAT           = "if (predicate.Invoke(new KeyValuePair<string,object>(\"{0}\", model.{1}))) {{ members.Add(\"{0}\", model.{1}); }}";
            const string WRITE_TIMESTAMP_FORMAT = "model.{0} = DateTime.UtcNow; if (predicate.Invoke(new KeyValuePair<string,object>(\"{0}\", model.{1}))) {{ members.Add(\"{0}\", model.{1}); }}";
            const string WRITE_STRING_FORMAT    = "if (predicate.Invoke(new KeyValuePair<string,object>(\"{0}\", model.{1}.ToString()))) {{ members.Add(\"{0}\", model.{1}.ToString()); }}";

            if (fillCompileType == DataIgnoreType.Read)
            {
                var custom = (member as DataReadCustomInfo);

                if (custom != null)
                {
                    if (custom.AssociatedNamespaces != null)
                    {
                        namespaces.AddRange(custom.AssociatedNamespaces.Select(ns => string.Format("using {0};", ns)));
                    }

                    var value = string.Format(READ_FORMAT, typeof(string).Name, member.ReadName);

                    return(string.Format(SET_CUSTOM_FORMAT, member.Member.Name, custom.ReadFormat.Replace("@value", value)));
                }
                else
                {
                    var value = string.Format(READ_FORMAT, member.TypeName, member.ReadName);

                    return(string.Format(SET_FORMAT, member.Member.Name, member.TypeName, value));
                }
            }
            else             // (implicit) if (fillCompileType == DataIgnoreType.Write)
            {
                var custom = (member as DataReadCustomInfo);

                if (custom != null)
                {
                    if (custom.AssociatedNamespaces != null)
                    {
                        namespaces.AddRange(custom.AssociatedNamespaces.Select(ns => string.Format("using {0};", ns)));
                    }
                }

                var specialAttribute = member.Member.GetCustomAttribute <DataSpecialTypeAttribute>();
                if (specialAttribute != null)
                {
                    // implement more ...
                    // use switch ...
                    switch (specialAttribute.DataType)
                    {
                    case SpecialDataType.Timestamp:
                    {
                        return(string.Format(WRITE_TIMESTAMP_FORMAT, member.ReadName, member.Member.Name));
                    }

                    case SpecialDataType.AsString:
                    {
                        return(string.Format(WRITE_STRING_FORMAT, member.ReadName, member.Member.Name));
                    }
                    }
                }

                return(string.Format(WRITE_FORMAT, member.ReadName, member.Member.Name));
            }
        }