예제 #1
0
        private ListFilter <T> Compile()
        {
            var            uniqueCode = GetUniqueCode();
            ListFilter <T> resultFilter;

            if (!FiltersCache.TryGetValue(uniqueCode, out resultFilter))
            {
                var includeAssemblies = new HashSet <string>();

                var provider = new CSharpCodeProvider(new Dictionary <string, string>()
                {
                    { "CompilerVersion", "v3.5" }
                });

                var name = "Filter";
                if (FilterBy != null)
                {
                    name += "_" + Regex.Replace(FilterBy, @"\W", "");
                }
                if (SortFields != null)
                {
                    name += "_Sort_" + Regex.Replace(SortFields.Aggregate((y, x) => y), @"\W", "");
                }
                var typeName = provider.CreateValidIdentifier(name);


                var targetTypeName = typeof(T).FullName.Replace('+', '.');
                var code           = new StringBuilder();
                code.AppendLine("using System;");
                code.AppendLine("using System.Collections;");
                code.AppendLine("using System.Collections.Generic;");
                code.AppendLine("using System.Linq;");
                code.AppendLine("using ASC.Api.Collections;");
                code.AppendLine("using System.Globalization;");

                code.AppendFormat("public class {1} : ListFilter<{0}> {{\r\n", targetTypeName, typeName);
                code.AppendFormat(
                    "    public override IEnumerable<{0}> FilterList(IEnumerable<{0}> items, bool sortDescending, FilterOperation operation, string[] filterValues){{\r\n",
                    targetTypeName);
                //Do a needed operations

                //TODO: Do a null checks!
                if (ShouldFilter())
                {
                    try
                    {
                        var filters      = FilterBy.Split(',');
                        var filterChecks = new List <string>();
                        foreach (var filter in filters)
                        {
                            var propInfo = GetPropertyInfo(filter).Where(x => x != null).ToList();
                            foreach (var propertyInfo in propInfo)
                            {
                                includeAssemblies.Add(propertyInfo.PropertyType.Assembly.Location);
                            }

                            var byProperty = GetPropertyPath(propInfo);

                            var nullCheck = GetNullCheck("item", propInfo);


                            filterChecks.Add(string.Format("({1}Satisfy(operation, filterValues, item.{0}{2}))",
                                                           byProperty,
                                                           string.IsNullOrEmpty(nullCheck) ? "" : (nullCheck + " && "),
                                                           GetPropertyToString(propInfo.Last())));
                        }
                        code.AppendFormat(
                            "items = items.Where(item =>{0});\r\n", string.Join(" || ", filterChecks.ToArray()));
                    }
                    catch (Exception)
                    {
                    }
                }
                if (ShouldSort())
                {
                    var propInfo = SortFields.Select(x => GetPropertyInfo(x)).Where(x => x != null).ToList();
                    //Add where
                    if (propInfo.Any())
                    {
                        foreach (var info in propInfo)
                        {
                            foreach (var propertyInfo in info)
                            {
                                includeAssemblies.Add(propertyInfo.PropertyType.Assembly.Location);
                            }

                            var nullCheck = GetNullCheck("item", info);
                            if (!string.IsNullOrEmpty(nullCheck))
                            {
                                code.AppendFormat("items=items.Where(item=>{0});", nullCheck);
                                code.AppendLine();
                            }
                        }

                        var byProperties = propInfo.Select(x => GetPropertyPath(x)).ToList();
                        code.AppendLine("items = sortDescending");
                        code.AppendFormat("?items.OrderByDescending(item => item.{0})", byProperties.First());
                        foreach (var byProperty in byProperties.Skip(1))
                        {
                            code.AppendFormat(".ThenByDescending(item => item.{0})", byProperty);
                        }

                        code.AppendFormat(": items.OrderBy(item => item.{0})", byProperties.First());
                        foreach (var byProperty in byProperties.Skip(1))
                        {
                            code.AppendFormat(".ThenBy(item => item.{0})", byProperty);
                        }
                        code.AppendLine(";");
                    }
                }

                code.AppendFormat("return items;\r\n");
                code.AppendLine("} }");

                var assemblyName = "filter" + Guid.NewGuid().ToString("N");
                var cp           = new CompilerParameters
                {
                    GenerateExecutable      = false,
                    OutputAssembly          = assemblyName,
                    GenerateInMemory        = true,
                    TreatWarningsAsErrors   = false,
                    CompilerOptions         = "/optimize /t:library",
                    IncludeDebugInformation = false,
                };

                cp.ReferencedAssemblies.Add("mscorlib.dll");
                cp.ReferencedAssemblies.Add("system.dll");
                cp.ReferencedAssemblies.Add("System.Core.dll");
                cp.ReferencedAssemblies.Add(GetType().Assembly.Location);
                cp.ReferencedAssemblies.Add(typeof(T).Assembly.Location);
                foreach (var includeAssembly in includeAssemblies)
                {
                    cp.ReferencedAssemblies.Add(includeAssembly);
                }

                var cr = provider.CompileAssemblyFromSource(cp, code.ToString());
                if (!cr.Errors.HasErrors)
                {
                    var assembly      = cr.CompiledAssembly;
                    var evaluatorType = assembly.GetType(typeName);
                    var evaluator     = Activator.CreateInstance(evaluatorType);
                    resultFilter = evaluator as ListFilter <T>;
                }
                //Add anyway!!!
                FiltersCache.Add(uniqueCode, resultFilter);
            }
            return(resultFilter);
        }