2016-07-27 115 views
3

我试图创建一个通用的方式来保存什么属性我应该搜索反对给定的类。创建泛型与子类

我已经创建了下面的结构来保存这些信息:

public struct Lookup<T> where T: BaseEntity 
{    
    public Expression<Func<T, object>> Parent { get; set; } 
} 

然后创建了一个字典如下:

readonly Dictionary<string, Lookup<BaseEntity>> _dict = 
    new Dictionary<string, Lookup<BaseEntity>>(); 

我有一个使用BaseEntity作为基类的类:

public class Agency : BaseEntity 
{ 
    public int AgencyId { get; set; } 
} 

我用这个信息创建一个新的Lookup结构体:

new Lookup<Agency> 
{ 
    Parent = x => x.Id 
}; 

但是,如果我尝试添加这对我的字典里,我得到了以下错误:

Cannot convert from Lookup<Agency> to Lookup<BaseEntity>

我本来以为这会工作,因为他们有相同的基本类型的,什么是这个方法。

我有相当数量的实体的补充,从而希望能做到这一点一般,而不必做,如果/开关等

感谢

+2

读入协方差。 –

回答

3

没有,Lookup<BaseEntity>不是Lookup<Agency>基本类型。 Agency源自BaseEntity的事实是不够的。但首先,让我们看看别的东西。

想想通常的方差规则。你的方法对应于

object DoSomething(T x) { ... } 

现在,在Lookup<BaseEntity>,这成为

object DoSomething(BaseEntity x) { ... } 

到目前为止,一切都很好 - 这是完全合法的传递Agency代替BaseEntity,因为AgencyBaseEntity派生。但是,的情况并非如此。你创造了这个:

object DoSomething(Agency x) { ... } 

很显然,你不能传递BaseEntity,而不是Agency - 这将彻底打破打字。和Java不同,C#(和.NET的泛型)在编译时和运行时都是真实的,它们不会回落到Lookup<BaseEntity>

此外,C#/ .NET限制了方差的使用。你可以在简单的表达式和委托中获得自由,但不能在类或泛型类中使用。你需要明确你想要的差异类型,并使用一个接口。例如,你的情况,你有这样的事情:

public interface ILookup<out T> 

这将允许你做演员从ILookup<Agency>ILookup<BaseEntity>。但是,对于你的情况来说这还不够,因为T在你的情况下是同变异和反变异的 - 换句话说,你不能在任何一个方向投射。

但是,这并不是什么大问题,因为你有点过分复杂。当你需要强类型创建Lookup<Agency>,你不需要它的类型本身 - 你要与非类型化Expression小号反正是工作:

public sealed class Lookup 
{ 
    private readonly Expression parent; 

    private Lookup(Expression parent) 
    { 
    this.parent = parent; 
    } 

    public Expression Parent { get { return parent; } } 

    public static Lookup For<T>(Expression<Func<T, object>> member) 
    where T : BaseEntity 
    { 
    return new Lookup(member); 
    } 
} 
+0

太棒了!很好的答案。 – niksofteng

+0

好吧,我并不期待这样的答案!这正是我所寻找的,感谢您的帮助! – ADringer