Advertisement
BradleyUffner

Untitled

Sep 7th, 2017
185
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.41 KB | None | 0 0
  1. static public class DataImporter
  2. {
  3.     private class PropertyData
  4.     {
  5.         public PropertyInfo Prop { get; set; }
  6.         public TypeConverter Converter { get; set; }
  7.     }
  8.  
  9.     public class StringToListOptions
  10.     {
  11.  
  12.         public StringToListOptions()
  13.         {
  14.             SplitLines = (input) => input.Split('\n');
  15.             SplitProperties = (input) => input.Split(',');
  16.             PropertyProcessingChain = new List<Func<string, string>>()
  17.             {
  18.                 (input) => input.Trim()
  19.             };
  20.         }
  21.  
  22.         /// <summary>
  23.         ///  A function that splits the source data in to individual lines.
  24.         /// </summary>
  25.         public Func<string, string[]> SplitLines { get; set; }
  26.  
  27.         /// <summary>
  28.         ///  A function that splits a source line in to individual properties.
  29.         /// </summary>
  30.         public Func<string, string[]> SplitProperties { get; set; }
  31.  
  32.         /// <summary>
  33.         ///  A list of Func<string, string> that accepts a string, modifies it, then return it. Defaults to "(input) => input.Trim()".
  34.         /// </summary>
  35.         internal List<Func<string, string>> PropertyProcessingChain { get; }
  36.  
  37.         /// <summary>
  38.         ///  Clears the list of property processors.
  39.         /// </summary>
  40.         public void ClearPropertyProcessingChain()
  41.         {
  42.             PropertyProcessingChain.Clear();
  43.         }
  44.  
  45.         /// <summary>
  46.         ///  Adds a new Func<string, string> that accepts a string, modifies it, and returns it.
  47.         /// </summary>
  48.         public void AddPropertyProcessor(Func<string, string> processor)
  49.         {
  50.             PropertyProcessingChain.Add(processor);
  51.         }
  52.     }
  53.  
  54.     /// <summary>
  55.     /// Converts a string in to a List<T> by splitting it in to lines, and lines in to properties.
  56.     /// </summary>  
  57.     /// <param name="input">
  58.     /// The string to convert.
  59.     /// </param>
  60.     /// <param name="properties">
  61.     /// A list of property to convert and map to T, in the order they appear in the input string,
  62.     /// in the format "t => new {t.Property1, t.Property2}"
  63.     /// </param>
  64.     public static List<T> ConvertToList<T>(this string input,
  65.                                           Expression<Func<T, object>> fields) where T : new()
  66.     {
  67.         return ConvertToList(input, fields, new StringToListOptions());
  68.     }
  69.  
  70.     /// <summary>
  71.     /// Converts a string in to a List<T> by splitting it in to lines, and lines in to properties.
  72.     /// </summary>
  73.     /// <param name="input">
  74.     /// The string to convert
  75.     /// </param>
  76.     /// <param name="properties">
  77.     /// A list of property to convert and map to T, in the order they appear in the input string,
  78.     /// in the format "t => new {t.Property1, t.Property2}"
  79.     /// </param>
  80.     /// <param name="options">
  81.     /// Options that control how the input string is parsed.
  82.     /// </param>
  83.     public static List<T> ConvertToList<T>(this string input,
  84.                                           Expression<Func<T, object>> properties,
  85.                                           StringToListOptions options) where T : new()
  86.     {
  87.         string[] propertyList = GetPropertyNamesFromExpression();
  88.         var targetType = typeof(T);
  89.         var propertyData = FindPropertyInfo();
  90.         var list = new List<T>();
  91.         var rawSource = options.SplitLines(input);
  92.         foreach (var rawLine in rawSource)
  93.         {
  94.             var item = new T();
  95.             list.Add(item);
  96.             var rawFields = options.SplitProperties(rawLine);
  97.  
  98.             if (propertyData.Count != rawFields.Length)
  99.             {
  100.                 throw new ArgumentException("String data does not contain the same number of fields as the list of fields.", nameof(input));
  101.             }
  102.  
  103.             int propertyIndex = 0;
  104.             foreach (var field in propertyData)
  105.             {
  106.                 var rawField = rawFields[propertyIndex];
  107.                 foreach (var processor in options.PropertyProcessingChain)
  108.                 {
  109.                     rawField = processor(rawField);
  110.                 }
  111.                 field.Prop.SetValue(item, field.Converter.ConvertFromString(rawField));
  112.                 propertyIndex++;
  113.             }
  114.         }
  115.         return list;
  116.  
  117.         string[] GetPropertyNamesFromExpression()
  118.         {
  119.             try
  120.             {
  121.                 return ((NewExpression)properties.Body).Arguments.Select(argument => ((MemberExpression)argument).Member.Name).ToArray();
  122.             }
  123.             catch (Exception)
  124.             {
  125.                 throw new ArgumentException($"Syntax Error: '{nameof(properties)}' must be an expression that returns an anonmous type containing a list of properties, e.g.: t => new {{t.Property1, t.Property2}}", nameof(properties));
  126.             }
  127.         }
  128.  
  129.         List<PropertyData> FindPropertyInfo()
  130.         {
  131.             var data = new List<PropertyData>();
  132.  
  133.             foreach (var field in propertyList)
  134.             {
  135.                 var item = new PropertyData();
  136.                 data.Add(item);
  137.                 item.Prop = targetType.GetProperty(field, BindingFlags.Public | BindingFlags.Instance);
  138.                 item.Converter = TypeDescriptor.GetConverter(item.Prop.PropertyType);
  139.             }
  140.             return data;
  141.         }
  142.     }
  143. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement