emr*_*can 5 c# linq predicate linq-to-sql
我正在开发多层应用程序解决方案,我的解决方案如下所示
我的Business.Process项目(业务层)只知道Business.DomainObject和Data.Repository项目,因此不知道并且与 Data.Sql.Entity 项目没有关系
我将业务(域)对象发送到存储库并执行在这个项目内部进行映射,然后我在存储库层内使用关系数据层进行 CRUD 过程。
我的传统领域对象是这样的,它只有属性
public class UserBO
{
public string Email { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的业务层类是这样的,
Repository r = new UserRepository();
r.Insert(myUserDomainObject);
Run Code Online (Sandbox Code Playgroud)
一切都很好,但是我的“谓词”查询有一些问题。我的存储库接口中有一个方法
bool IsExists(Expression<Func<BusinessObject,bool>> predicate);
Run Code Online (Sandbox Code Playgroud)
并像这样在我的业务层中使用它;
Repository r = new UserRepository(); <br/>
r.IsExists(p => p.Email.Equals("email address"));
Run Code Online (Sandbox Code Playgroud)
如您所见,它的参数是“业务对象”,但我的实际存储库(与数据库连接)使用我的 dbml 文件内的“数据对象”。
public override bool IsExists(Expression<Func<DataObject, bool>> predicate){
return _table.Where(predicate).Any();
}
Run Code Online (Sandbox Code Playgroud)
我想转换这两个谓词,例如我将发送 UserBO 并转换为 UserDataObject
我怎样才能做到这一点?
您必须分析 LambdaExpression 的参数和主体并构建一个新表达式。您可以使用 predicate.Parameters 访问它使用的主体predicate.Body和参数。新表达式具有 UserBO 类型的参数,而不是 UserDataObject。此外,主体中的 ParameterExpression 必须使用新参数。
当然,这是假设这是一个简单的场景,其中BO和DataObject具有相同的属性。更复杂的转换是可能的,但需要对表达式树进行更深入的分析。
为了给您一个起点,我制作了一个具有非常相似的 BusinessObject 和 DataObject 的示例。关键组件是一个从 ExpressionVisitor 派生的类,它执行转换:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace ConvertExpression
{
public class BusinessObject
{
public int Value { get; set; }
}
public class DataObject
{
public int Value { get; set; }
}
internal class ExpressionConverter : ExpressionVisitor
{
public Expression Convert(Expression expr)
{
return Visit(expr);
}
private ParameterExpression replaceParam;
protected override Expression VisitLambda<T>(Expression<T> node)
{
if (typeof(T) == typeof(Func<BusinessObject, bool>))
{
replaceParam = Expression.Parameter(typeof(DataObject), "p");
return Expression.Lambda<Func<DataObject, bool>>(Visit(node.Body), replaceParam);
}
return base.VisitLambda<T>(node);
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node.Type == typeof(BusinessObject))
return replaceParam; // Expression.Parameter(typeof(DataObject), "p");
return base.VisitParameter(node);
}
protected override Expression VisitMember(MemberExpression node)
{
if (node.Member.DeclaringType == typeof(BusinessObject))
{
var member = typeof(DataObject).GetMember(node.Member.Name, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).FirstOrDefault();
if (member == null)
throw new InvalidOperationException("Cannot identify corresponding member of DataObject");
return Expression.MakeMemberAccess(Visit(node.Expression), member);
}
return base.VisitMember(node);
}
}
public class ConvertExpression
{
public static void Main()
{
BusinessObject[] bos = { new BusinessObject() { Value = 123 }, new BusinessObject() { Value = 246 } };
DataObject[] dos = { new DataObject() { Value = 123 }, new DataObject() { Value = 246 } };
Expression<Func<BusinessObject, bool>> boExpr = x => x.Value == 123;
var conv = new ExpressionConverter();
Expression<Func<DataObject, bool>> doExpr = (Expression<Func<DataObject, bool>>) conv.Convert(boExpr);
var selBos = bos.Where(boExpr.Compile());
Console.WriteLine("Matching BusinessObjects: {0}", selBos.Count());
foreach (var bo in selBos)
Console.WriteLine(bo.Value);
var compDoExpr = doExpr.Compile();
var selDos = dos.Where(doExpr.Compile());
Console.WriteLine("Matching DataObjects: {0}", selDos.Count());
foreach (var dataObj in selDos)
Console.WriteLine(dataObj.Value);
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3976 次 |
| 最近记录: |