简体   繁体   English

为 TryParse 使用动态数据类型

[英]Use dynamic data type for TryParse

I have a process that allows users to upload data in Excel file and save to database once the data have gone series of validations.我有一个过程,允许用户在 Excel 文件中上传数据,并在数据经过一系列验证后保存到数据库。 Once such validation is data type validation, to prevent them trying to put a string into integer field, for example.一旦这样的验证是数据类型验证,例如,为了防止他们试图将字符串放入 integer 字段。 Here is an excerpt of the code.这是代码的摘录。 The caller (ValidateContentDataType) calls ValidateDataType() and passes property info and data in string to the callee to perform TryParse.调用者(ValidateContentDataType)调用 ValidateDataType() 并将字符串中的属性信息和数据传递给被调用者以执行 TryParse。


    public void ValidateContentDataType()
    {
       //Do stuff
       ValidateDataType(typeof(T).GetProperty("nameOfProperty"), data);
       //Do stuff
    }

    private bool ValidateDataType(PropertyInfo propInfo, string dataElement)
    {
        if (propInfo is null) return true;

        if (propInfo.PropertyType == typeof(decimal) || propInfo.PropertyType == typeof(decimal?))
        {
            return decimal.TryParse(dataElement, out decimal temp);
        }

        //Other ifs TryParse for different data type....
        return true;
    }

While this works, I don't like the series of ifs in ValidateDataType().虽然这有效,但我不喜欢 ValidateDataType() 中的一系列 ifs。 Instead of series of ifs for different data types, like this:而不是针对不同数据类型的一系列 ifs,如下所示:

 if (propInfo.PropertyType == typeof(decimal) || propInfo.PropertyType == typeof(decimal?))
        {
            return decimal.TryParse(dataElement, out decimal temp);
        }

is it possible to have something like this:是否有可能有这样的东西:

  return *propertyType*.TryParse(dataElement, out *propertyType *temp);

Stylistically, I'd probably write that as a switch statement:在风格上,我可能会把它写成一个switch语句:

switch (propInfo.PropertyType)
{
  case typeof(decimal):
  case typeof(decimal?):
    return decimal.TryParse(dataElement, out decimal temp);
  case typeof(int):
  case typeof(int?):
    return ...
}

I think that looks a lot better than multiple if statements.我认为这看起来比多个if语句要好得多。 But I freely admit that it's a subjective opinion.但我坦率地承认这是一个主观意见。

There might be a solution that involves creating a generic method that expects a type that implements the IParseable interface.可能有一个解决方案涉及创建一个泛型方法,该方法需要一个实现IParseable接口的类型。 Something like:就像是:

private bool ValidateDataType<T>(...) where T:IParseable

But I haven't completely worked it out.但是我还没有完全弄清楚。 Might be that you'd have to call the method through reflection.可能是您必须通过反射调用该方法。

OK.好的。 IParsable gives me what I need. IParsable 给了我我需要的东西。 Creating a couple of extensions with the the type parameter T that implements IParsable.使用实现 IParsable 的类型参数 T 创建几个扩展。 Then invoke the extensions so I can use the property types from reflection.然后调用扩展,以便我可以使用来自反射的属性类型。 Seems to be a lot of work for something seemingly trivia.为了一些看似琐碎的事情,似乎要下很多功夫。 Anyway, here is what I came up with:无论如何,这是我想出的:

 internal class Program
    {
        static void Main(string[] args)
        {
            Type myClassType = typeof(MyClass);
            PropertyInfo propInfo = myClassType.GetProperty("ForecastYear");
            ValidateDataType(propInfo.PropertyType, "2023");
        }

        static void ValidateDataType(Type propertyType, string input)
        {
            MethodInfo method = typeof(TryParseExtensions).GetMethod(nameof(TryParseExtensions.TryParse));
            MethodInfo generic = method.MakeGenericMethod(propertyType);
            
            object[] args = { input, null };
            var parseSuccessful = (bool)generic.Invoke(null, args);
            var parsedValue = args[1];
        }
    }

    static class TryParseExtensions
    {
        public static T Parse<T>(this string s) where T : IParsable<T>
        {
            return T.Parse(s, null);
        }      

        public static bool TryParse<T>(this string? s, [MaybeNullWhen(false)] out T result) where T : IParsable<T>
        {
            result = default(T);
            if (s == null) { return false; }
            try
            {
                result = s.Parse<T>();
                return true;
            }
            catch { return false; }
        }
    }

    public class MyClass{
        public int ForecastYear { get; set; }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM