繁体   English   中英

如何动态检查动态linq中的空对象?

[英]How to check null object in dynamic linq on th fly?

我正在使用动态linq来生成一些请求。 除了当一个类为空时,所有的一切都很好。 我得到了NullException 所以,我想做同样的事情:

dossiers = dossiers.Where(d => d != null && d.Demandeurs != null && 
           d.Demandeurs.Any(DossierTiers => DossierTiers != null &&
           DossierTiers.Tiers != null && DossierTiers.Tiers.TiersLiesEnfantsActifs != null &&
           DossierTiers.Tiers.TiersLiesEnfantsActifs.Any(TiersLie => TiersLie != null && TiersLie.TiersEnfant != null &&
           TiersLie.TiersEnfant.AdressePrincipale != null && TiersLie.TiersEnfant.AdressePrincipale.Adresse != null &&                
           TiersLie.TiersEnfant.AdressePrincipale.Adresse.CodePostal.StartsWith("45")))).ToList();

我不知道如何检查null

您在那里缺少一项检查,那么应该没问题:TiersLie.TiersEnfant.AdressePrincipale.Adresse.CodePostal!= null。 从而:

dossiers = dossiers.Where(d => d != null && d.Demandeurs != null && 
           d.Demandeurs.Any(DossierTiers => DossierTiers != null &&
           DossierTiers.Tiers != null && DossierTiers.Tiers.TiersLiesEnfantsActifs != null &&
           DossierTiers.Tiers.TiersLiesEnfantsActifs.Any(TiersLie => TiersLie != null && TiersLie.TiersEnfant != null &&
           TiersLie.TiersEnfant.AdressePrincipale != null && TiersLie.TiersEnfant.AdressePrincipale.Adresse != null &&                
TiersLie.TiersEnfant.AdressePrincipale.Adresse.CodePostal != null &&           TiersLie.TiersEnfant.AdressePrincipale.Adresse.CodePostal.StartsWith("45")))).ToList();

由于您有很多!=空值检查,因此最好将它们减少到必要的数量。 例如,应该检查d => d != null ,因为它的null时无论如何都不应该出现,因为该元素不存在(对于任何(a=> a != null构造都相同)。元素不应该因为它们不存在而“出现”,在答案中我让它静止不动,这样我所做的代码更改只是使程序正常工作所需的最小限度。

编辑:考虑原始命令(在注释中提到):

dossiers = dossiers.Where(d => 
           d.Defendeurs.Any(DossierTiers => DossierTiers.Tiers != null && 
           DossierTiers.Tiers.TiersLiesEnfantsActifs != null && 
           DossierTiers.Tiers.TiersLiesEnfantsActifs.Any(
                TiersLie => TiersLie.TiersEnfant != null && 
                TiersLie.TiersEnfant.AdressePrincipale != null && 
                TiersLie.TiersEnfant.AdressePrincipale.Adresse.CodePostal != null && 
                TiersLie.TiersEnfant.AdressePrincipale.Adresse.CodePostal.Contains("45"))))
          .ToLi‌​st();

我支持这样的意见,即您的模型应设计为避免空值-通过将成员集合初始化为空集合,而不是将它们默认为空值。 但是,如果这不是一个选择,则应将您可能会重复的空检查逻辑提取到一个单独的方法中,该方法可以使main子句更易于重用。

public bool IsValidDossier(Dossier d)
{
    return d != null 
           && d.Defendeurs.Any(DossierTiers => 
              DossierTiers.Tiers != null 
              && DossierTiers.Tiers.TiersLiesEnfantsActifs != null 
              && DossierTiers.Tiers.TiersLiesEnfantsActifs.Any(TiersLie =>       
                     TiersLie.TiersEnfant != null 
                     && TiersLie.TiersEnfant.AdressePrincipale != null 
                     && TiersLie.TiersEnfant.AdressePrincipale.Adresse.CodePostal != null;
}

public bool DossierMatchesPostalCode(Dossier d, string codePostal)
{
    return d.Defendeurs.Any(dt => dt.Tiers.TiersLiesEnfantsActifs.Any(tl => tl.TiersEnfant.AdressePriincipal.Adresse.CodePostal.Contains(codePostal);

}

在主代码中,您可以重复使用它:

var relevantDossiers = 
   dossier.Where(d => IsValidDossier(d) && DossierMatchesPostalCode(d, "45"));

这是我用于生成动态linq的函数(基于网上的一些函数):

        public static Expression GetExpression(Expression parameter, object Operator, object value, params string[] properties)
        {
            Expression resultExpression = null;
            Expression childParameter, navigationPropertyPredicate;
            Type childType = null;

            if (properties.Count() > 1)
            {
                parameter = Expression.Property(parameter, properties[0]);
                var isCollection = typeof(IEnumerable).IsAssignableFrom(parameter.Type);
                if (isCollection)
                {
                    childType = parameter.Type.GetGenericArguments()[0];
                    childParameter = Expression.Parameter(childType, childType.Name);
                }
                else
                {
                    childParameter = parameter;
                }
                var innerProperties = properties.Skip(1).ToArray();
                navigationPropertyPredicate = GetExpression(childParameter, Operator, value, innerProperties);
                if (isCollection)
                {
                    var anyMethod = typeof(Enumerable).GetMethods().Single(m => m.Name == "Any" && m.GetParameters().Length == 2);
                    anyMethod = anyMethod.MakeGenericMethod(childType);
                    navigationPropertyPredicate = Expression.Call(anyMethod, parameter, navigationPropertyPredicate);
                    resultExpression = BuildLambda(parameter, navigationPropertyPredicate);
                }
                else
                {
                    resultExpression = navigationPropertyPredicate;
                }
            }
            else
            {
                ConstantExpression right = null;
                var childProperty = parameter.Type.GetProperty(properties[0]);
                var left = Expression.Property(parameter, childProperty);
                right = (value != null) ? right = Expression.Constant(value, value.GetType()) : Expression.Constant(string.Empty);
                navigationPropertyPredicate = GetExpression(left, right, Operator);
                resultExpression = BuildLambda(parameter, navigationPropertyPredicate);
            }
            return resultExpression;
        }


       private static Expression GetExpression(MemberExpression left, ConstantExpression right, Object p)
        {
            MethodInfo c = null;
            if (p is OperatorUsedWithString)
            {
                switch ((OperatorUsedWithString)p)
                {
                    case OperatorUsedWithString.CommencePar:
                        c = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
                        return Expression.Call(left, c, right);
                    case OperatorUsedWithString.Contient:
                        c = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
                        return Expression.Call(left, c, right);
                    case OperatorUsedWithString.TerminePar:
                        c = typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
                        return Expression.Call(left, c, right);
                    case OperatorUsedWithString.Egal:
                        c = typeof(string).GetMethod("Equals", new Type[] { typeof(string) });
                        return Expression.Call(left, c, right);

                }
            }
            if (p is OperatorUsedWithNumber)
            {
                switch ((OperatorUsedWithNumber)p)
                {
                    case OperatorUsedWithNumber.Egal:
                        return Expression.Equal(left, right);
                    case OperatorUsedWithNumber.Inferieur:
                        return Expression.LessThan(left, right);
                    case OperatorUsedWithNumber.InferieurEgal:
                        return Expression.LessThanOrEqual(left, right);
                    case OperatorUsedWithNumber.Superieur:
                        return Expression.GreaterThan(left, right);
                    case OperatorUsedWithNumber.SuperieurEgal:
                        return Expression.GreaterThanOrEqual(left, right);



                }
            }
            if (p is OperatorUsedWithDateTime)
            {
                switch ((OperatorUsedWithDateTime)p)
                {
                    case OperatorUsedWithDateTime.PasPresent:
                        return Expression.Equal(left, Expression.Constant(null));
                    case OperatorUsedWithDateTime.Present:
                        return Expression.NotEqual(left, Expression.Constant(null));
                }


            }
            throw new NotImplementedException();
        }
    }

和BuildLambda:

       private static Expression BuildLambda(Expression parameter, Expression predicate)
        {
            var resultParameterVisitor = new ParameterVisitor();
            resultParameterVisitor.Visit(parameter);
            var resultParameter = resultParameterVisitor.Parameter;
            return Expression.Lambda(predicate, (ParameterExpression)resultParameter);
        }

我想,我只是对此功能进行了更改,但尝试了一些方法,但没有任何效果。 因此,欢迎您提供一些帮助。

我在query字符串中使用null检查

searchQ +=
    $"({objPropertiesName[i]} != null && " +
    $"{objPropertiesName[i]}.ToLower().Contains" +
    $"(\"{searchTerm}\")) || ";

它的工作就像一种魅力。

暂无
暂无

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

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