2016-12-19 3 views
2

Можно ли упростить эту логику, существует ли общий способ сделать это. Код находит отмеченные атрибуты и анализирует его в соответствии с типом атрибута. Пожалуйста, предложите какой-то способ оптимизации этого кода, все типы данных класса Product будут строковыми, я получаю входной файл, так как xml напрямую преобразует сериализованные данные в класс с decimal, int, float не даст правильного сообщения об ошибке, If есть список элементов, которые он вызывает ошибку в xml, мы не знаем, какая строка вызвала ошибку.Динамически конвертировать свойство в тип

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using System.Text; 
using System.Threading.Tasks; 

namespace TestSolution 
{ 
    public interface ICustomParser 
    { 
     bool Parse(string input); 
    } 

    public class DecimalParserAttribute : Attribute, ICustomParser 
    { 
     public bool Parse(string input) 
     { 
      if (input == null) return false; 

      decimal decimalValue; 

      return decimal.TryParse(input, out decimalValue); 
     } 
    } 

    public class intParserAttribute : Attribute, ICustomParser 
    { 
     public bool Parse(string input) 
     { 
      if (input == null) return false; 

      int intValue; 

      return int.TryParse(input, out intValue); 
     } 
    } 

    public class Product 
    { 
     [DecimalParser] 
     public string Weight { get; set; } 

     [intParser] 
     public string NoOfItems { get; set; } 

     [intParser] 
     public string GRodes { get; set; } 

     [intParser] 
     public string WRodes { get; set; } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 

      var sb = Validate(new Product() { NoOfItems = "1", GRodes = "4", Weight = "5", WRodes = "23" }); 

      Console.WriteLine(sb); 
      sb = Validate(new Product() { NoOfItems = "1", GRodes = "4w", Weight = "5", WRodes = "23" }); 

      Console.WriteLine(sb); 
      Console.ReadKey(); 
     } 

     private static string Validate(Product product) 
     { 
      var sb = new StringBuilder(); 

      foreach (var property in product.GetType().GetProperties()) 
      { 
       var value = Convert.ToString(property.GetValue(product, null)); 

       var sel = property.GetAttribute<ICustomParser>(); 

       if (sel == null) continue; 

       var parserinstance = (ICustomParser)Activator.CreateInstance(sel.GetType()); 

       if (parserinstance.Parse(value)) continue; 

       sb.AppendLine(string.Format("{0} Has invalid value", property.Name)); 
      } 
      return sb.ToString(); 
     } 
    } 

    public static class Extensions 
    { 
     public static T GetAttribute<T>(this PropertyInfo property) 
     { 
      return (T)property.GetCustomAttributes(false).Where(s => s is T).FirstOrDefault(); 
     } 
    } 
} 
+1

Это может быть лучше подходит для [CodeReview] (http://codereview.stackexchange.com). – HimBromBeere

+0

Мне нравится ваш метод, я не знаю, – Esperento57

ответ

0

Если у вас есть только один тип (Product), это, вероятно, не стоит - просто написать код проверки явно не все модные вещи. Однако, если у вас есть несколько типов для инспектирования (возможно, известно только во время выполнения):


Это действительно зависит от того, насколько быстро оно должно быть. Как часто это выполняется? Если периодическая, то есть не огромное количество, чтобы сделать - основное изменение будет просто бросить анализатор непосредственно:

var parserInstance = (ICustomParser)sel; 

(это уже является тип атрибута)

Если это критический путь, то есть лот, который вы можете сделать, чтобы усилить его, но вы попадаете в область метапрограммирования - по сути, это то, что делают большинство инструментов, таких как сериализаторы и ORM, для уменьшения отражения во время выполнения. Если вы не знакомы с взломом IL во время выполнения, я бы рекомендовал посмотреть на инструмент типа «Sigil» (доступный на nuget), из-за которого трудно ошибиться (или, по крайней мере: сообщает , что вы сделали неправильно). По существу, вы можете проверить структуру данных, а затем испустить IL, который соответствует тому, как он будет выглядеть, если вы делаете все это в явном коде; например, излучающий ИЛ, который выглядит как:

static readonly DecimalParserAttribute _decimal = new DecimalParserAttribute(); 
public static void Validate(Product product) { 
    var sb = new StringBuilder(); 
    if(!_decimal.Parse(product.Weight)) { 
     sb.Append(...); 
    } 
    // ... etc 
    ..., 
} 
Смежные вопросы