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

彼らは同じベース型であるように私が何であるか、これが働くだろうと思っているだろうこれはラウンドです。

私は、Lookup<BaseEntity>Lookup<Agency>の基本型ではないなど/切り替えた場合ので、それを行うことを期待して、一般的ではなく、やって持っていた追加する

おかげ

+2

。 –

答えて

3

を実体のかなりの数を持っています。 AgencyBaseEntityから派生しているという事実は十分ではありません。しかし、まず、何か他のものを見てみましょう。

通常の分散ルールについて考えてみましょう。あなたの方法は

object DoSomething(T x) { ... } 

に対応し、Lookup<BaseEntity>で、これは、これまでのところは良い

object DoSomething(BaseEntity x) { ... } 

なり - AgencyBaseEntityから派生するので、それは、BaseEntityの代わりにAgencyを渡すために完全に合法です。しかし、それはそうではないあなたは持っています。完全にタイピングを壊すこと - あなたはBaseEntity代わりのAgencyを渡すことはできません、明らかに

object DoSomething(Agency x) { ... } 

:あなたはこれを作成しました。 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

関連する問題