private Expression CreateTypeCheckExpression(MemberExpression memberExpression, Expression typeValueExpression) { string typeName; if (typeValueExpression.NodeType == ExpressionType.Constant) { typeName = (typeValueExpression as ConstantExpression).Value.ToString(); } else if (typeValueExpression.NodeType == ExpressionType.MemberAccess) { typeName = GetMemberValue((typeValueExpression as MemberExpression)).ToString(); } else { throw new NotSupportedException("Type name must be either a string literal or constant class member."); } HashSet <int> typeDbIds; ModelType.TryGetNotAbstractIncludingDerivedTypeDbIds(new string[] { typeName }, out typeDbIds); bool nullable = IsNullable(memberExpression.Type); Expression newMemberExpression = memberExpression; if (nullable) { newMemberExpression = Expression.Convert(newMemberExpression, typeof(int)); } Expression typeCheckExpression = Expression.Call( Expression.Constant(typeDbIds), typeDbIds.GetType().GetMethod(nameof(HashSet <int> .Contains)), newMemberExpression); if (nullable) { Expression notNullExpression = Expression.MakeBinary(ExpressionType.NotEqual, memberExpression, Expression.Constant(null)); typeCheckExpression = Expression.AndAlso(notNullExpression, typeCheckExpression); } return(typeCheckExpression); }
protected override Expression VisitTypeBinary(TypeBinaryExpression node) { var expression = Visit(node.Expression); if (expression.Type != node.Expression.Type) { HashSet <int> typeDbIds = null; Expression <Func <int> > x = () => typeDbIds.Count; ModelType.TryGetNotAbstractIncludingDerivedTypeDbIds(new string[] { node.TypeOperand.FullName }, out typeDbIds); Expression typePropAccess = Expression.MakeMemberAccess( expression, typeof(TDbEntity).GetProperty(nameof(IDbEntity.Type), BindingFlags.Instance | BindingFlags.Public)); return(Expression.Call( Expression.Constant(typeDbIds), typeDbIds.GetType().GetMethod(nameof(HashSet <int> .Contains)), typePropAccess)); } return(base.VisitTypeBinary(node)); }