C# 铸造/映射代表

C# 铸造/映射代表,c#,entity-framework,delegates,automapper,func,C#,Entity Framework,Delegates,Automapper,Func,我有办法 public List<DTO.User> GetUsers(Func<Domain.User, bool> expression) { var users = new List<DTO.User>(); using(UserContext context = new UserContext()) { // obviously an error us

我有办法

  public List<DTO.User> GetUsers(Func<Domain.User, bool> expression)
  {
        var users = new List<DTO.User>();

        using(UserContext context = new UserContext())
        {
           // obviously an error
           users = context.Users.ToList();
        }

        return users;

   }
public List GetUsers(Func表达式)
{
var users=新列表();
使用(UserContext=newusercontext())
{
//显然是个错误
users=context.users.ToList();
}
返回用户;
}
注意DTO.User(DTO)和Domain.User(EF中的域实体) 所以我使用AutoMapper来映射像这样的实体

  public List<DTO.User> GetUsers()
  {
        var users = new List<DTO.User>();

        using(UserContext context = new UserContext())
        {

           Mapper.CreateMap<Domain.User, DTO.User>();
           users = 
           Mapper.Map<List<Domain.User>,List<DTO.User>>(context.Users.ToList());
        }

       return users;

   }
公共列表GetUsers()
{
var users=新列表();
使用(UserContext=newusercontext())
{
CreateMap();
用户=
Map(context.Users.ToList());
}
返回用户;
}
好吧,这看起来不错,但是。。我希望GetUser方法接受委托表达式作为参数。我在ui中有一个显示用户列表的网格,它有许多过滤选项,所以我希望我的ui只调用一个方法,而不是为每个过滤器创建一个方法

  // filter by username
  List<DTO.User> users = userBL.GetUsers(u => u.UserName.Contains(txtUserName.Text));

  // filter by ID
  List<DTO.User> users = userBL.GetUsers(u => u.== txtUserID.Text);

  ...
//按用户名筛选
List users=userBL.GetUsers(u=>u.UserName.Contains(txtUserName.Text));
//按ID筛选
List users=userBL.GetUsers(u=>u.==txtUserID.Text);
...
所以我在我的DAL层中提出了这样的想法

  public List<DTO.User> GetUsers(Func<DTO.User, bool> expression)
  {
        var users = new List<DTO.User>();

        using(UserContext context = new UserContext())
        {
           Mapper.CreateMap<Domain.User, DTO.User>();

           Func<Domain.User, bool> predicate;

           // this is an error on AutoMaper
           predicate = Mapper.Map<Func<DTO.User,bool>, Func<Domain.User, bool>>(expression)

           // I also tried direct casting which is an obvious fail
           //predicate = (Func<Domain.User,bool>)expression;

           users = 
           Mapper.Map<Domain.User, DTO.User>(context.Users.Where(predicate).ToList());
        }

       return users;

   }
public List GetUsers(Func表达式)
{
var users=新列表();
使用(UserContext=newusercontext())
{
CreateMap();
Func谓词;
//这是Automper上的一个错误
谓词=Mapper.Map(表达式)
//我还尝试了直接铸造,这是一个明显的失败
//谓词=(Func)表达式;
用户=
Map(context.Users.Where(predicate.ToList());
}
返回用户;
}

因此,基本上,我试图将DTO委托转换或映射到Domain delaget,以便在Domain.User列表的.Where()方法中使用。可能吗?提前感谢。

我几乎可以肯定您无法将委托映射到另一个委托,但您的代码存在更多问题:

  • 如果将
    Func
    传递给Linq to实体查询,您将执行与现在相同的操作。它将从数据库中提取所有数据,并在应用程序服务器的内存中执行过滤器。您必须传递
    表达式
    ,才能在DB服务器上执行它
  • 我不知道您的整个体系结构和应用程序的复杂性,但我觉得将DTO的转换直接放在DAL中是不好的。我可以想象只有在EFv1中使用
    EntityObjects
    时才能这样做

如果您仍然喜欢使用委托,您可以找到有关该委托的更多信息

我认为转换Func是不可能的,因为它包含编译语句,但您可以接受表达式而不是Func;通过这种方式,您可以得到一个抽象语法树,您可以对其执行转换。但是,这很容易出错,也很麻烦,除非您只有很少的期望条件。我只希望为.Where()提供筛选条件。我在这里遇到了麻烦,Func to Func检查这一点。我的目标是在筛选时不从数据库中提取所有数据,这就是为什么我在UI中有谓词GetUser(u=>u.ID==ID)应等同于从ID=@ID的用户中选择*。。。但是,正如你所说,我必须学习表达式才能做到这一点,谢谢回到问题上来,我如何才能将表达式转换为表达式?是的,我还认为在上面提到的BLAs中移动DTO转换,实际上可以将表达式的语法树解析为表达式;这是LINQtoSQL策略的一部分,用于创建要执行的sql语句。但这意味着要遍历一棵包含几乎所有C#/.NET语言结构的树,为什么这不是一项简单的任务