是否有可能简化这种逻辑,是否有通用的方法来做到这一点。 代码查找标记的属性并根据属性类型对其进行解析。 请建议一些优化此代码的方法,Product类的所有数据类型都是字符串,我得到的产品输入为xml直接将序列化数据转换为带有decimal的类,int,float不会给出正确的错误信息,如果有的话是在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();
}
}
}
答案 0 :(得分:0)
如果你只有一种类型(Product
),它可能是不值得的 - 只需明确地编写验证代码而不需要任何花哨的东西。但是,如果要检查多种类型(可能仅在运行时知道):
这取决于它需要多快。这种情况多久发生一次?如果它是周期性的,则没有大量的事情要做 - 主要的变化是直接投射解析器:
var parserInstance = (ICustomParser)sel;
(已经 属性类型)
如果它是关键路径,那么你可以做一些 lot 来加强它,但你进入元编程领域 - 这实际上是大多数工具如序列化器和ORM所做的事情。减少运行时反射。如果你不熟悉在运行时黑客攻击IL,我建议你看一下像Sigil这样的工具(在nuget上可用),这很难弄错(或至少:告诉你什么你做错了)。从本质上讲,您可以检查数据结构,然后发出 IL,它与您在显式代码中完成所有内容的情况相匹配;例如,发出看起来有点像的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
...,
}