簡體   English   中英

轉換功能 <T1,bool> 到功能 <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;
        }
    }
}

在某些時候,當您擁有AbstractFactoryRepository<T>AbstractDomainObject時,協方差和對數會變得非常復雜。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM