我有一个DTO和POCO,我使用Func<T,bool>
代表“where”。 DTO和POCO实体具有相同的属性(属性的名称和类型)。
我设法转换 - 使用ExpresionsVisitor类将DTO表达式转换为POCO表达式。
我使用表达式将相关实体(entity.Include)和Func包含在其中。
下面有一个代码示例,我需要帮助实现翻译方法。
我该怎么做?
public class Program
{
static void Main(string[] args)
{
ADTO a = new ADTO
{
Id = 1,
Name = "Test"
};
Func<ADTO,bool> dtoFunc = (dto => dto.Id == 1);
Func<A, bool> func = Translate(dtoFunc);
}
private static Func<A, bool> Translate(Func<ADTO, bool> dtoFunc)
{
// Implementation here
throw new NotImplementedException();
}
}
public class A
{
public int Id { get; set; }
public String Name { get; set; }
}
public class ADTO
{
public int Id { get; set; }
public String Name { get; set; }
}
答案 0 :(得分:2)
你不能“翻译”一个功能。由于强类型,您需要实现它。 你需要的是ADTO到A的翻译,这是微不足道的:
private A Translate(ADTO adto)
{
return new A() { Id = adto.Id, Name = adto.Name);
}
然后你需要了解你实际在做什么。 “函数”是对数据的执行,它不是数据本身。所以你需要两个实现,但它们是相同的:
Func<A, bool> funcA = (a => a.Id == 1);
Func<ADTO, bool> funcADTO = (adto => adto.Id == 1);
接下来,您需要统一它们。这是真正的罪魁祸首。你需要的是告诉编译器谁是谁,选择其中一个案例(只有一个,而不是全部):
A extends ADTO
ADTO extends A
A extends AbstractDataTransferObject, ADTO extends AbstractDataTransferObject
A implements IDataTransferObject, ADTO implements IDataTransferObject
我建议的是抽象版本,它有几个优点。 那时你可以这样做:
Func<AbstractDataTransferObject, bool> f = (adto => adto.Id == 1);
对所有衍生产品使用一个函数实现,包括A和ADTO。
显然,抽象版本将包含公共属性,即您显示的所有属性:Id和Name。我知道你在现实世界的应用程序中会有更多的属性和类型。
您真正想要的是从有效负载中抽象出DTO功能,以便您可以实现通用存储库。这就是我多年前所做的,至少。稍后的问题是注入lambda以独立于派生类型过滤数据,但这是可能的。
迟早你会发现你必须非常(非常)理解这些论点:covariance and contravariance
我可以给你一些帮助:
http://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
编辑2:
回复评论我是如何实施CRUD的:我没有。
CRUD是DAO的概念,就像DTO一样。在我的代码中,我使用了存储库模式和工作单元,这是一种概括,没有外观。
这是解释差异的快速链接:http://thinkinginobjects.com/2012/08/26/dont-use-dao-use-repository/
存储库以这种方式使用:
public List<Customer> GetOlderThan(int minimumAge, bool lazy)
{
using(Repository<Customer> repo = RepositoryFactory.Create<Customer>(lazy))
{
return repo.Retrieve(c => c.Age >= minimumAge);
}
}
正如您在3行中所看到的,您可以实现一个转换为SQL的查询:
SELECT * FROM Customers WHERE Age >= @minimumAge;
实现通用存储库时的 final 问题是注入过滤谓词。指向解决方案的指针是谓词实际上是这样的:
Func<bool, T>
其中T是实际实体类型(例如Customer
)。要查询客户,它将是:
Func<bool, Customer>
通用存储库将是:
Repository<Customer>
那就是说,实施Repository<T>
是一个血浴,因为你需要从一个独特的类(AbstractDomainObject
在我的情况下)派生所有实体,它必须兼容使用实际的实体框架。
你写的AbstractDomainObject
几乎一样:
public abstract class AbstractDomainObject
{
private int _id = -1;
public int ID
{
get
{
if (_id == -1)
{
throw new InvalidOperationException("domain object not yet persisted");
}
return _id;
}
set
{
if (_id != -1)
{
throw new InvalidOperationException("domain object already persisted");
}
_id = value;
}
}
public bool IsPersisted
{
get
{
return _id != -1;
}
}
}
在某些时候,当你拥有AbstractFactory
,Repository<T>
和AbstractDomainObject
时,协方差和逆变得非常复杂。