2016-07-27 216 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