2013-08-16 46 views
2

考虑:转换函数功能<TDao, bool>到Func键<TEntity,bool>的

class MyDao 
{ 
    public int SiteId {get;set;} 

    public Cv3AddressDao ReadSingle(Expression<Func<Cv3AddressDao, bool>> predicate) 
    { //... 
    } 
} 

class MyEntity 
{ 
    public int SiteId {get;set;} 
} 

我如何可以采取Expression<Func<MyDao, bool>>类型的谓词参数,并将其转换为Expression<Func<MyEntity, bool>>

类型答案我找

请注意,答案必须表明转换是如何工作的。我想实现与此类似但工作原理:)......

public MyDao ReadSingle(Expression<Func<MyDao , bool>> predicate) 
    { 
     var mappedPredicate = MapFun<MyDao , MyEntity>(predicate); 
     var result = repository.GetSingle<MyEntity>(mappedPredicate); 

     return Convert(result);//Converts Entity to Dao...safe to ignore this line 
    } 

    Expression<Func<B, bool>> MapFun<A, B>(Expression<Func<A, bool>> input) 
    { 
     Expression<Func<B, bool>> result = null;//How to convert? 
     return result; 
    } 

关于我为什么要这样设计细节...

这是一个asp.net MVC 5应用程序。此转换很重要的原因是我的视图不知道类型MyEntity。换句话说,如果我是这样做:

myDaoObject.ReadSingle<MyEntity>(myEntity => myEntity.SiteId == "123");

然后我查看层,因为在这里我使用MyEntity引用我的DLL层。我想View层与道工作,而不是:

myDaoObject.ReadSingle<MyDao>(myDao=> myDao.SiteId == "123");

可是,现在我不得不清道转换,使其可用与库。存储库只知道DL对象。我试图避免创建一个冗余的Repository来支持这个翻译。 DAO包含实体的所有属性加上一些。

+0

你能告诉我们你调查和尝试过什么吗? – Default

+0

@默认 - 问题更新了一个接近我需要的实现。 –

回答

2

我没有准确的代码,但您可能想要使用提供的表达式并自行执行等同转换。

This stackoverflow question是我所要做的。从P.Brian.Mackey

注简称回答工作。使用乔恩的答案可以做到这一点。然而,答案的公开部分最终成为Func<>转换的不可见球员。我需要的全部是:

Expression<Func<B, bool>> MapFun<A, B>(Expression<Func<A, bool>> input)where A : class 
    { 
     var result = DbAccessLayer.TransformPredicateLambda<A,B>(input); 
     return result; 
    } 

请注意,这种方法是私人的。我将它改为公开。请参阅上面引用的答案中的@Jon回答以获取完整的实现。

public static Expression<Func<TNewTarget, bool>> TransformPredicateLambda<TOldTarget, TNewTarget>(Expression<Func<TOldTarget, bool>> predicate) 
0

为什么不能通过它在

public Cv3AddressDao ReadSingle<TEntity>(Expression<Func<TEntity, bool>> predicate) 
{ 
    // ... 
} 
... 
var dao = new MyDao(); 
var addr = dao.ReadSingle<MyEntity>(x => x.SiteId == 1); 
+0

这会导致我的视​​图层耦合到我的数据层。道的一点是,我没有这种耦合。即使有更新,它也要求在视图中定义lamba。我不明白这将如何工作。 –

+0

@ P.Brian.Mackey你没有提到你的问题中的图层,也许你应该更新你的问题,所以它*清晰*你的要求是什么。在你详细描述你的应用程序体系结构之前,很难修改我的答案。 – James

+0

我更新了问题。希望这将清除一切。 –

1

让他们都有一个共同的接口:

public interface ISited { 
    int SiteId {get; set; } 
} 

class MyDao : ISited { .. } 
class MyEntity : ISited { .. } 

,并使用通用接口代替C3VAddressDao对泛型类型参数的约束:

public ISited ReadSingle(Expression<Func<ISited, bool>> predicate) 

当然,这可能不是没有其他常见的有用您将包括在ISited中。

+0

这是一个好主意,但在尝试它时我发现,因为我在存储库中使用'DbContext.Set ()',所以我无法使用它。我需要在Func <>之间进行转换,或者如果不可行,请完全做其他事情。 –

0
public static Expression<Func<B, bool>> MapFun<A, B>(Expression<Func<A, bool>> input) where A : class 
    { 
     return b => input.Compile()((b as A)); 
    } 

这应该为你工作,因为你只是转换参数。

更新:

根据您更新的答案,您有几个选项。

使用反射来从实体到DAO(看像AutoMapper

你有另一种选择是定义使用类似IConvertable你2种类型之间的转换定制复制值。

+0

唉,这么近......运行时错误:'没有强制操作符被定义在类型'System.Boolean'和'MvcApplication1.Models.MyEntity'之间。' –

+0

@ P.Brian.Mackey编辑我的答案,基本上你想调用输入用B代替A类型,所以你需要将B投给A,由于编译时错误而增加了约束。 – Eluvatar

+0

不同的运行时错误:LINQ to Entities不支持LINQ表达式节点类型'Invoke'。我突然间遇到了TFS问题。将不得不把这一点表... –

相关问题