![](/img/trans.png)
[英]Is there a way to map Func<T1, bool> to Func<T2, bool>?
[英]Convert Func<T1,bool> to Func<T2,bool>
我有一個DTO和POCO,並且我將Func<T,bool>
用作“ where”。 DTO和POCO實體具有相同的屬性(屬性的名稱和類型)。
我已經設法進行轉換-使用ExpresionsVisitor類將DTO表達式轉換為POCO表達式。
我使用表達式將相關實體(entity.Include)和Func包括在哪里。
下面是一個代碼示例,我需要實現Translate方法的幫助。
我怎樣才能做到這一點?
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; }
}
您不能“翻譯”功能。 由於類型強,您需要實現它。 您需要的是將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以獨立於派生類型來過濾數據,但是這是可能的。
遲早您會發現必須非常(非常)理解以下論點: 協方差和逆方差
我可以給您更多幫助:
http://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
編輯2:
回答我如何實施CRUD的評論:我沒有。
就像DTO一樣,CRUD是DAO的概念。 在我的代碼中,我使用了存儲庫模式和工作單元,這是一種概括,並且沒有外觀。
這是一個解釋差異的快速鏈接: 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;
實現通用存儲庫時的最后一個問題是過濾謂詞的注入。 解決方案的一個指針是謂詞確實是這樣的:
Func<bool, T>
其中T是實際實體類型(例如Customer
)。 要查詢客戶,它將是:
Func<bool, Customer>
通用存儲庫將是:
Repository<Customer>
就是說,實現Repository<T>
就像洗血浴,因為您需要從唯一類(在我的情況下為AbstractDomainObject
)派生所有實體,並且它必須與實際的Entity Framework 兼容 。
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
時,協方差和對數會變得非常復雜。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.