2012-02-10 11 views
2

私は流暢なnhibernateで動的な基本マッピングを作成しようとしています。メンバーアクセスfuncをFunc <DerivedFromT、ob​​ject>からFuncにキャスト<T,object>

私はベースマップ< T>によってチェックインされてやっている:のClassMap < T>たとえば場合: (typeof演算(ICategorizedEntity).IsAssignableFrom(typeof演算(T)))

そうであれば、IたくはICategorizedEntityのインターフェイスに属し、「カテゴリー」という名前のプロパティをマッピングしますが、マップ(機能)関数はTのプロパティを受け入れるので、私は、LINQと少しを推測しようとしたし、この思い付いた:「doesnの

Expression<Func<ICategorizedEntity, object>> exp = x => x.Category; 
    var parameter = Expression.Parameter(typeof (T)); 
    var lmd = Expression.Lambda<Func<T, object>>(exp, parameter); 
    Map(lmd); 

'Map'関数の深い内部で次のことをチェックするので、作業しません:

MemberExpression memberExpression = (MemberExpression) null; 
    if (expression.NodeType == ExpressionType.Convert) 
     memberExpression = ((UnaryExpression) expression).Operand as MemberExpression; 
    else if (expression.NodeType == ExpressionType.MemberAccess) 
     memberExpression = expression as MemberExpression; 
    if (enforceCheck && memberExpression == null) 
     throw new ArgumentException("Not a member access", "expression"); 

「メンバーアクセスではありません\ r \ nパラメータ名:式」が表示されます。

MemberExpressionなどを作成してキャストするにはどうすればよいですか?

答えて

2

おかげダグラス、あなたは右の(簡単な)答えに私をリードしています。

私は(ラムダ式の内側)古き良き変換がトリックをした

...それを見つけようとしすぎて行きました:あなたの素敵な説明ダグラス

Map(x => ((ICategorizedEntity)x).Category); 
2

Func<DerivedFromT,object>は、DerivedFromTパラメータを受け入れる方法を表す。 Func<T,object>は、Tパラメータを受け入れるメソッドを表します。 C#4で導入されたdelegate varianceによって、Func<T,object>Func<DerivedFromT,object>にキャストできますが、それ以外の方法ではリクエストできません。

これが何を意味するかを考えてみて:Promote方法は、デリゲートFunc<Student,object>に一致しながら、この場合

public class Person { } 

public class Student : Person { } 

public static class School 
{ 
    public static object Greet(Person person) 
    { 
     return null; 
    } 

    public static object Promote(Student student) 
    { 
     return null; 
    } 
} 

を、Greet方法は、デリゲートFunc<Person,object>と一致します。

Func<Person, object> greetPerson = School.Greet; 
Func<Student, object> promoteStudent = School.Promote; 

我々はFunc<Student,object>Greetをキャストすることができます。 Personを迎えることができれば、StudentPersonの特殊な形式であることが保証されています)を迎えることもできます。

Func<Student, object> greetStudent = greetPerson; 

しかし、我々はFunc<Person,object>Promoteをキャストすることはできません。 Studentを宣伝することはできますが、Studentでない限り、一般にPersonを宣伝することはできません。

Func<Person, object> promotePerson = promoteStudent; // Will not compile. 

我々はPersonが学生であることがわかっている場合、我々はそれをキャストすることによって、これを示すことができます:

Func<Person, object> promotePerson = 
    personWhoIsActuallyStudent => promoteStudent((Student)personWhoIsActuallyStudent); 
+0

おかげで、しかし、私はあなたが何を誤解だと思います私は達成しようとした.. 良い古い変換は、このトリックでした: Map(x =>((ICategorizedEntity)x).Category); –

+0

私は本当にあなたの質問を理解していないと認めます。私の投稿は主にあなたのタイトルに基づいていました。しかし、私は、あなたが必要とするインラムダキャストを実行するコードの最後の行に、おそらく答えがあると仮定しました。 – Douglas

+0

うん、それは私に答えを与えた –

関連する問題