using Microsoft.CSharp; using Microsoft.ML; using Microsoft.ML.Data; using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace testML { public static class DictionaryToObjectConverter { public static IEnumerable Convert(List> data, string toPredict, out Type classType, out DataViewSchema schema) { var schemaBuilder = new DataViewSchema.Builder(); var definition = new Dictionary(); var sample = data.FirstOrDefault(); if (sample != null) { foreach (var key in sample.Keys) { //Buscamos el tipo var sampleValue = (from x in data where x.ContainsKey(key) && x[key] != null select x[key]).FirstOrDefault(); if (sampleValue != null) { var keyType = sampleValue.GetType(); if (key == toPredict) { keyType = typeof(float); } definition.Add(key, keyType); if (keyType == typeof(string)) { schemaBuilder.AddColumn(key, TextDataViewType.Instance); } else if (keyType == typeof(double)) { schemaBuilder.AddColumn(key, NumberDataViewType.Double); } else if (keyType == typeof(float)) { schemaBuilder.AddColumn(key, NumberDataViewType.Single); } else if (keyType == typeof(int)) { schemaBuilder.AddColumn(key, NumberDataViewType.Int32); } else if (keyType == typeof(long)) { schemaBuilder.AddColumn(key, NumberDataViewType.Int64); } } } } var converter = new DictionaryToObjectConverterClass() { ClassName = "OBJ" + Guid.NewGuid().ToString("N").ToUpper(), ToPredict = toPredict, Definition = definition }; var classCode = converter.TransformText(); string exDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory().Trim(Path.DirectorySeparatorChar); CompilerParameters compilerParameters = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = true, IncludeDebugInformation = true, TreatWarningsAsErrors = false, CompilerOptions = string.Format("/target:library /lib:{0}", exDir) }; var mlDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); foreach (var item in AppDomain.CurrentDomain.GetAssemblies()) { compilerParameters.ReferencedAssemblies.Add(item.Location); } // compilerParameters.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location); CompilerResults compilerResults = new CSharpCodeProvider(new Dictionary { { "CompilerVersion", "v4.0" } }).CompileAssemblyFromSource(compilerParameters, new string[] { classCode } ); var dllAssembly = compilerResults.CompiledAssembly; classType = dllAssembly.GetType("DictionaryToObjectConverterNamespace." + converter.ClassName); Type listType = typeof(List<>); Type genericType = listType.MakeGenericType(classType); var result =(IList) Activator.CreateInstance(genericType) ; Dictionary translate = new Dictionary(); translate.Add(string.Empty, 0); foreach (var inputData in data) { if (inputData.ContainsKey(toPredict) && inputData[toPredict] != null) { if (!translate.ContainsKey(inputData[toPredict] as string)) { var max = translate.Values.Max()+1; translate.Add(inputData[toPredict] as string, max); } } } foreach (var inputData in data) { var outputData = (IDictionaryToObjectConverter)Activator.CreateInstance(classType); result.Add(outputData); foreach (var key in inputData.Keys) { if (key == toPredict) { outputData[key] = translate[inputData[key] as string ?? string.Empty]; } else { outputData[key] = inputData[key]; } } } schema = schemaBuilder.ToSchema(); return (IEnumerable)result; } } public partial class DictionaryToObjectConverterClass { public string ClassName { get; set; } public string ToPredict { get; set; } public Dictionary Definition { get; set; } } public interface IDictionaryToObjectConverter { object this[string propertyName] { get; set; } void SetValue(string propertyName, object value); object GetValue(string propertyName); } }