/// <summary>Option creation testing</summary> private static void OptionTest() { Console.Write("OptionTest:"); Options opt = new Options("test", "test_class"); opt.AddAssembly("System.Data.dll"); opt.AddClassAttribute("[DataContract]"); opt.AddPropertyAttributes("Something", new List<string>() { "[DataMember]" }); opt.AddPropertyType("abc", "System.String"); opt.AddConverter("abc", x => { return 1; }); opt.AddNamespace("system.namespace"); var props = opt.GetPropertyAttributes("someTHING"); if (props.Count == 1 && props[0] == "[DataMember]") { } else { Console.WriteLine("Invalid property attributes"); Console.WriteLine(Fail); return; } props = opt.GetPropertyAttributes("OTHER"); if (props.Count != 0) { Console.WriteLine("Invalid property attributes, should be empty"); Console.WriteLine(Fail); return; } var classAttributes = opt.GetClassAttributes(); if (classAttributes.Count == 1 && classAttributes[0] == "[DataContract]") { } else { Console.WriteLine("Invalid class attributes"); Console.WriteLine(Fail); return; } var assemblies = opt.GetAssemblies(); if (assemblies.Count == 1 && assemblies[0] == "System.Data.dll") { } else { Console.WriteLine("Invalid assembly set"); Console.WriteLine(Fail); return; } if (opt.GetPropertyType("abc") != "System.String") { Console.WriteLine("Incorrect type"); Console.WriteLine(Fail); return; } if (opt.GetPropertyType("xyz") != null) { Console.WriteLine("Type shouldn't be set"); Console.WriteLine(Fail); return; } if (opt.GetConverter("abc") == null) { Console.WriteLine("Incorrect converter"); Console.WriteLine(Fail); return; } if (opt.GetConverter("xyz") != null) { Console.WriteLine("Converter shouldn't be set"); Console.WriteLine(Fail); return; } var names = opt.GetNamespaces(); if (names.Length != 1 || names[0] != "system.namespace") { Console.WriteLine("Incorrect namespace set"); Console.WriteLine(Fail); return; } Console.WriteLine(Pass); }
/// <summary> /// Create an object wrapper from the given object /// </summary> /// <param name="objs">Object list to create from</param> /// <param name="options">Creation options</param> /// <returns>Object wrapper set from all the objects in the set</returns> public static IEnumerable<ObjectWrapper> CreateFromEnumerable(IEnumerable<object> objs, Options options) { if (objs == null) { throw new ArgumentNullException("objs"); } if (options == null) { throw new ArgumentNullException("options"); } if (objs.Any()) { Type type = objs.First().GetType(); Assembly assembly = null; if (!cached.TryGetValue(options.FullClass, out assembly)) { // Only allow anonymous types (why else would you call this?) // http://stackoverflow.com/questions/1650681/determining-whether-a-type-is-an-anonymous-type bool hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0; bool nameContainsAnonymousType = type.FullName.Contains(AnonymousType) || type.FullName.Contains(AnonType); bool anonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType; if (!anonymousType) { throw new InvalidOperationException("Class must be of anonymous type"); } // Build the class file StringBuilder classBuilder = new StringBuilder(); classBuilder.AppendLine(" using System; "); foreach (var name in options.GetNamespaces()) { classBuilder.AppendFormat(" using {0}; ", name); classBuilder.AppendLine(); } classBuilder.AppendFormat("namespace {0} ", options.Namespace); classBuilder.AppendLine("{"); foreach (var classAttribute in options.GetClassAttributes()) { classBuilder.AppendFormat(" {0} ", classAttribute); } classBuilder.AppendFormat("public class {0}", options.ClassName); classBuilder.AppendLine("{"); foreach (var property in type.GetProperties()) { var typeName = property.PropertyType.Name; var typeValue = options.GetPropertyType(property.Name); if (typeValue != null) { typeName = typeValue; } foreach (var propertyAttribute in options.GetPropertyAttributes(property.Name)) { classBuilder.AppendFormat(" {0} ", propertyAttribute); } classBuilder.AppendFormat(" public {0} {1} ", typeName, property.Name); classBuilder.AppendLine(" { get; set; } "); } classBuilder.Append("}"); classBuilder.Append("}"); // Compile it // http://stackoverflow.com/questions/9414008/c-sharp-use-reflection-to-build-a-class-to-build-a-dynamic-filehelper-class CompilerParameters parameters = new CompilerParameters(); parameters.GenerateExecutable = false; parameters.GenerateInMemory = true; parameters.IncludeDebugInformation = false; foreach (var assemblyName in options.GetAssemblies()) { parameters.ReferencedAssemblies.Add(assemblyName); } CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp"); CompilerResults compiledResults = compiler.CompileAssemblyFromSource(parameters, classBuilder.ToString()); if (compiledResults.Errors.HasErrors) { StringBuilder outputErrors = new StringBuilder(); for (int index = 0; index < compiledResults.Errors.Count; index++) { outputErrors.AppendLine(compiledResults.Errors[index].ErrorText); } outputErrors.AppendLine(classBuilder.ToString()); throw new InvalidOperationException("Invalid syntax or usage: " + outputErrors.ToString()); } assembly = compiledResults.CompiledAssembly; assembly = cached.GetOrAdd(options.FullClass, assembly); } foreach (var obj in objs) { var instance = assembly.CreateInstance(options.FullClass); var wrapper = new ObjectWrapper(instance); foreach (var property in type.GetProperties()) { var value = property.GetValue(obj, null); var converter = options.GetConverter(property.Name); if (converter != null) { value = converter(value); } wrapper.SetField(property.Name, value); } yield return wrapper; } } }