将 Expression<Func<DTOUser, bool>> 谓词转换为 Expression<Func<User, bool>> 谓词。

4

我在Expression中遇到了问题

我有一个实体

public class User{ 
public string Username{get;set;}
  public int PhoneNumber{get;set;}
  public string FIrstName{get;set;}
  public string LastName{get;set;}
}

我有一个DTO

public class DTOUser{
  public string Username{get;set;}
  public int PhoneNumber{get;set;}
  public string FIrstName{get;set;}
  public string LastName{get;set;}
  }

然后我有一个通用的代码片段

 public IList<DTOUser> SelectAll(Expression<Func<DTOUser, bool>> predicate)
    {
           using (var adc = _conn.GetContext())
        {   
       // what should I do ?? so i can convert Predciate to get all values from Users (Entity)   
//it generates an error because predicate can't be cast into Entity User                    
 //   var users = adc.Users.All(predicate);
       }          
    }

我希望通过传递LAMBDA表达式来获取DTOUser列表。
accountrepo.SelectAll( user => user.firstname.equals ("sample"));

我已经研究了这个问题,并得出结论,由于DTOUser和User是不同的类型,所以很难将表达式从一个类型转换为另一个类型。
Jon Skeet提出了一种解决方案: 如何将Expression<Func<T,DateTime>>转换为Expression<Func<T,object>> 但是,由于这种解决方案似乎需要将每个值从DTOUser映射到User,这是否会使它更加复杂,因为我的DTOUser包含超过15个属性。
有人能帮帮我吗?

根据我的理解,您想在类型为User的对象上应用期望类型DTOUser的表达式。您能否编辑问题,使其更清晰明了? - Miroslav Bajtoš
不知道如何删除我的重复标记,我只是读得太快了。对此我深表歉意。 - psycho
@MiroslavBajtoš 我想要的是将 Expression<func<DTOUsers,bool>> 转换为 Expression<func<Users,bool>>,以便谓词可以被 adc.Users.All(predicate) 接受。 - Salman
2个回答

2
你不能直接从一种类型转换为另一种类型,你可以采取以下方法:
  1. 手动映射
  2. 使用反射自动映射(因为属性名称相同)
  3. 使用AutoMapper
使用反射进行映射,你可以使用以下通用代码:
public static T1 CopyProperties<T1, T2>(T2 model)
    where T1 : new()
    where T2 : new()
{
    // Get all the properties in the model
    var type = model.GetType();
    var properties = type.GetProperties();

    var result = new T1();
    var resultType = result.GetType();
    var resultProperties = resultType.GetProperties();

    // Loop through each property
    foreach (var property in properties)
    {
        var resultProperty = resultProperties.FirstOrDefault(n => n.Name == property.Name && n.PropertyType == property.PropertyType);
        if (resultProperty != null)
        {
            resultProperty.SetValue(result, property.GetValue(model, null), null);
        }
    }
    return result;
}

它会复制相同类型和名称的属性。

旧解决方案中有24个表。如果我开始编写手动映射,它将耗费大量时间和代码维护成本。如果可能的话,请详细说明第二种方法,即使用反射自动地进行映射,附带一个小的代码示例。 - Salman
AutoMapper应该是一个很好的解决方案,因为类具有相同的属性名称。 - AlexH
谢谢你的帮助,真的非常感谢。我更喜欢使用Automapper。 - Salman

0

我认为你可以使用Jon Skeet在链接中的答案,并在User(部分)类中定义从DTOUser到User的显式转换:

public static explicit operator User(DTOUser dto)
{
    return new User
    {
        Prop1 = dto.Prop1,
        Prop2 = dto.Prop2,
        ...
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接