任何简单的方法来查看哪个IF条件是错误的?

时间:2016-06-08 19:13:40

标签: c# asp.net .net-4.0

我发布这个问题是为了找到一种更简单的方法来实现结果。

我们有一个很大的IF语句,用于检查NULLstring.empty。像这样:

if (string.IsNullOrEmpty(Empl.Name) || string.IsNullOrEmpty(Empl.last) ||
   string.IsNullOrEmpty(Empl.init) || string.IsNullOrEmpty(Empl.cat1) ||
   string.IsNullOrEmpty(Empl.history) || string.IsNullOrEmpty(Empl.cat2) ||
   string.IsNullOrEmpty(Empl.year) || string.IsNullOrEmpty(Empl.month) || 
   string.IsNullOrEmpty(Empl.retire) || string.IsNullOrEmpty(Empl.spouse) || 
   string.IsNullOrEmpty(Empl.children) || string.IsNullOrEmpty(Empl.bday) || 
   string.IsNullOrEmpty(Empl.hire)|| string.IsNullOrEmpty(Empl.death) || 
   string.IsNullOrEmpty(Empl.JobName) || string.IsNullOrEmpty(Empl.More) || 
   string.IsNullOrEmpty(Empl.AndMore))
{
    //Display message. Something like "Error: Name and Month is missing"
    return;
}

到目前为止,我发现的解决此问题的任何解决方案都非常耗时,并且需要编写更多代码。

有没有办法知道哪个值是string.IsNullOrEmpty而不必过多地改变这个IF语句?更糟糕的是,我可以单独检查每一个语句,但我不想这样做。

感谢。

6 个答案:

答案 0 :(得分:5)

不,没有"魔法"将告诉您OR语句中的一系列表达式中哪一个为真的函数。此外,由于您使用的是短路版本,因此该语句将在第一个真实条件之后返回true,因此其余的表达式甚至不会被评估

但是,可以执行以下操作:

bool[] checks = {
   string.IsNullOrEmpty(Empl.Name) , string.IsNullOrEmpty(Empl.last) ,
   string.IsNullOrEmpty(Empl.init) , string.IsNullOrEmpty(Empl.cat1) ,
   string.IsNullOrEmpty(Empl.history) , string.IsNullOrEmpty(Empl.cat2) ,
   string.IsNullOrEmpty(Empl.year) , string.IsNullOrEmpty(Empl.month) , 
   string.IsNullOrEmpty(Empl.retire) , string.IsNullOrEmpty(Empl.spouse) , 
   string.IsNullOrEmpty(Empl.children) , string.IsNullOrEmpty(Empl.bday) , 
   string.IsNullOrEmpty(Empl.hire) , string.IsNullOrEmpty(Empl.death) , 
   string.IsNullOrEmpty(Empl.JobName) , string.IsNullOrEmpty(Empl.More) , 
   string.IsNullOrEmpty(Empl.AndMore)
};

if(checks.Any())
{
    //Display message. Something like "Error: Name and Month is missing"
    return;
}

现在checks变量保存每个表达式的结果。

答案 1 :(得分:3)

我发现这种使用ModelState.isValid的方式更为优雅。

一些参考:What is ModelState.IsValid valid for in ASP.NET MVC in NerdDinner?

对于您的模型,您可以添加以下注释:

[Required(AllowEmptyStrings= false)]
public string Boo { get; set; }

进行验证时,请尝试:

if (!ModelState.IsValid) 
{
  //Display message. Something like "Error: Name and Month is missing"
  return;
}

答案 2 :(得分:1)

是的,编写自己的字符串扩展方法,执行相同的检查,但也接受List并将字段名称添加到列表中。在if之前声明字符串列表,您将获得评论所在的违规字段列表。

这可以通过一些反射来改进,以自动获取名称,并可能进行一些优化,但它是在正确的轨道上。

请记住,违反if语句的第一个条件会导致它失败,因此除非if构造方式不同,否则您将获得一个不完整的列表(一个项目)。

 public static class StringExtensions
        {

            public static bool CheckIsNullOrEmptyAndListIt(this string field, string fieldName, List<string> naughties)
            {
                var result = String.IsNullOrEmpty(field);
                if (result == true)
                {
                    naughties.Add(fieldName);
                }

                return result;
            }         
        }
    }

答案 3 :(得分:1)

using System.IO;
using System;
using System.Linq;


public class Program
{

    public class Dog
   {

    public static string Name {get;set;}
    public static string Race {get;set;}
   }

    public static bool validate(Dog dog)
    {
        bool val = true;
        var y  = dog.GetType()
                    .GetProperties()
                    .Select(p =>
                        {
                            object value =p.GetValue(dog,null);
                            if(string.IsNullOrEmpty(value.ToString())){ val=false; return false;}
                            else return true;

                        })
                    .ToArray();

         return val;
    }

    public static void Main()
    {
        Dog dog= new Dog();

        Dog.Name = "Peter";
        Dog.Race = "";

        if(validate(dog))
        {
             Console.WriteLine("Hello, World!");
        }


    }
}

答案 4 :(得分:0)

您可以使用以下内容:

public static class ValidationHelper
{
    public static IEnumerable<string> FindEmptyProperties<T>(T target, params Expression<Func<T, string>>[] propertySelectors)
    {
        foreach (var propertySelector in propertySelectors)
        {
            if (string.IsNullOrEmpty(propertySelector.Compile()(target)))
            {
                var memberExpr = propertySelector.Body as MemberExpression;
                yield return memberExpr.Member.Name;
            }
        }
    }
}

用法:

var failed = ValidationHelper.FindEmptyProperties(Empl, x => x.Name, x => x.last, x => x.init, x => x.cat1).ToList();
if (failed.Any())
{
    throw new InvalidOperationException(
        string.Format("Error: {0} is missing", 
            string.Join(", ", failed)));
}

答案 5 :(得分:0)

如果使用ASP.NET MVC,可以使用DataAnnotations ...

对于一般的c#上下文考虑PostSharp面向方面的库! Geat项目!

否则:也许是使用普通.NET的反射解决方案? (专为您设计!我想我可能会为自己的项目保留)

使用不同类型,您可以控制目标绑定标志。

为数据传输对象提供公共基类。 (DTO)

反思是性能优化的,也适用于泛型!

public class Program
{
    public void Main()
    {
        Empl test = new Empl()
        {
            TestProp = "blub",
            TestInt = 1
        };

        if (test.ValidateProperties(Validations.CheckEmptyStringsAndZeroInts))
        {
            Console.WriteLine("validation passed");
        }
        else
        {
            Console.WriteLine("validation failed");
        }
    }
}
private static class Validations
{
    //put this in a static class with standard checks
    public static Func<object, bool> CheckEmptyStringsAndZeroInts = o =>
    {
        if (o is string && string.IsNullOrEmpty((string)o))
        {
                return false;
        }
        else if (o is int && ((int) o) == 0)
        {
            return false;
        }

        // ignore other property types
        return true;
    };
}
// Derive all your models like this. deriving from an Empl class is still valid and working!
//[IncludeBindingFlagsForPropertyReflctionAttribute(/*your custom binding flags*/)] //can also override the binding flags in derived classes!
public class Empl : DtoBase<Empl>
{
    public string TestProp { get; set; }

    public int TestInt { get; set; }

    // Your properties here
}

// Helps you to control the targeted properties. you can filter for public or protected members for example
public class IncludeBindingFlagsForPropertyReflctionAttribute : Attribute
{
    public BindingFlags BindingFlags { get; }
    public IncludeBindingFlagsForPropertyReflctionAttribute(BindingFlags propertySearchBindingFlags)
    {
        BindingFlags = propertySearchBindingFlags;
    }
}

//Looks much. But used once as base class can do those validations for you
[IncludeBindingFlagsForPropertyReflction(BindingFlags.Public | BindingFlags.Instance)]
public abstract class DtoBase<TDto> where TDto : DtoBase<TDto>
{
    private static Dictionary<Type, List<PropertyInfo>> DtoPropertyInfosStorage { get; }

    private List<PropertyInfo> DtoPropertyInfos => DtoPropertyInfosStorage[typeof (TDto)];

    static DtoBase()
    {
        DtoPropertyInfosStorage = new Dictionary<Type, List<PropertyInfo>>();

        Type tDto = typeof (TDto);

        var includeBindingFlagsForProperty = GetAttribute(tDto);

        BindingFlags defaultTargetFlags = BindingFlags.Instance | BindingFlags.Public;

        DtoPropertyInfosStorage.Add(typeof(TDto), new List<PropertyInfo>(typeof(TDto).GetProperties(includeBindingFlagsForProperty?.BindingFlags ?? defaultTargetFlags)));
    }

    private static IncludeBindingFlagsForPropertyReflctionAttribute GetAttribute(Type dtoType)
    {
        bool stopRecursion = !dtoType.IsSubclassOf(typeof(DtoBase<TDto>));

        var includeBindingFlagsForProperty = dtoType.GetCustomAttributes(typeof(IncludeBindingFlagsForPropertyReflctionAttribute)).FirstOrDefault();

        if (includeBindingFlagsForProperty == null && !stopRecursion)
        {
            return GetAttribute(dtoType.BaseType);
        }

        return null;
    }

    /// <summary>
    /// You can handle your validation type in you validation function yourself.
    /// </summary>
    public bool ValidateProperties(Func<object, bool> validationFunction)
    {
        foreach (KeyValuePair<Type, List<PropertyInfo>> dtoPropertyInfo in DtoPropertyInfosStorage)
        {
            foreach (PropertyInfo propertyInfo in DtoPropertyInfos)
            {
                if (!validationFunction(propertyInfo.))
                {
                    return false;
                }


            }
        }

        return true;
    }

    /// <summary>
    /// You can pass your targeted property type like string to TPropertyType
    /// <![CDATA[ Example:
    /// if(ValidateProperties<string>(validate => !string.IsNullOrEmpty(validate)))
    /// {
    ///     properties not empty?
    /// }
    /// ]]]]>
    /// </summary>
    public bool ValidateProperties<TPropertyType>(Func<TPropertyType, bool> validationFunction)
    {
        List<PropertyInfo> targetPropertyInfos =
            DtoPropertyInfos.Where(prop => prop.PropertyType == typeof (TPropertyType))
                .ToList();

        foreach (PropertyInfo dtoPropertyInfo in targetPropertyInfos)
        {
            if (validationFunction((TPropertyType) dtoPropertyInfo.GetValue(this)))
            {
                return false;
            }
        }

        return true;
    }
}