2011-01-13 16 views
2

私のドメインモデルでは、すべてのクラスが派生する基本エンティティクラスがあります。
現在のユーザーの権限に基づいてフィルタを動的に作成したいと考えています。
たとえば、Employeeクラスの場合、従業員は自分自身とその部門を見ることができると定義します。
私の方法は、このような何か行くだろう:
呼び出す静的メソッドを動的に決定する

public static IQueryable<Employee> CreateLinqFilter(IQueryable<Employee> query, User user) 
    { 
     return query.Where(e => e.Id == user.Id || e.Department.Manager.Id == user.Id); 
    } 

をしてから、私のリポジトリの基底クラスで、私は動的にタイプを決定し、正しいCreateLinqFilterメソッドを呼び出すしたいと思います:

protected IQueryable CreateLinq<T>(User user) 
    { 
     var query = Session.Linq<T>(); 
     Type t = typeof(T); 
     //if not an entity- do not perform filter 
     if (!t.IsAssignableFrom(typeof(Entity))) 
     { 
      return query; 
     } 
     //now we know that T is a sub-class of Entity. 
     return CreateLinqFilter<T>(query,user); 
    } 

protected IQueryable CreateLinqFilter<T>(IQueryable<T> query, User user) 
     //the following line won't compile: 
     //where T: Entity 
    { 
     //i'd like to be able to do: 
     //T.CreateFilter(query); 

     //instead, I have to do this? 
     if (typeof(T) == Employee) 
     { 
      return Employee.CreateLinqFilter(query,user); 
     } 
     if (typeof(T) == Department) 
     { 
      return Department.CreateLinqFilter(query,user); 
     } 
     //etc... 
    } 

私が今までに得た唯一の解決策は、非常に見苦しいif-elseブロックがたくさんあることです。
誰かが良いアイデアを得ましたか?
おかげ
ジョニー

+0

私はここに何かが欠けていますが、あなたのEntityクラスで "CreateLinqFilter"を宣言してから、このすべてのrelfection型の代わりに宣言してください。単に "entity.CreateLinqFilter私が言うように、おそらく何かが足りなくて、何かを知りたいのですが;-) – Chris

+0

@Chris CreateLinqFilter関数がエンティティのCollections *に作用するので、それはかなりです単一のエンティティのコンテキストで無意味です;機能は実際には静的です... –

+0

ああ、それは理にかなっています。私は時折、ジェネリックスの周りに頭を抱えて、彼らが生きる必要がある:) :) – Chris

答えて

1

のようなものを試してみてください:

return (IQueryable)typeof(T).GetMethod("CreateLinqFilter").Invoke(null, new object[]{query, user}); 

これは、実行時にメソッドを見つけるためにリフレクションを使用しています。これが遅すぎる場合は、GetMethodの結果をどこかにキャッシュすることを検討してください。このメソッドは静的メソッドに限定されないことに注意してください。 nullをT型のオブジェクトへのポインタに置き換え、通常のインスタンスメソッドでも同様に使用できます。

詳細については、MSDN documentation for the reflection classesを参照してください。 documentation for Invokeに良い例があります。 C#4.0で

+0

よく、しかし、それは動作し、現時点では最高の答えと思われます。ありがとう! –

0

、あなたは、いない場合は、多分あなたは最初のオフ、if..elseブロックの多くを使用していない、

+0

ありがとう、私はそれを少し試してみましょう私が.net 4.0にアップグレードする週... –

0

まあ最初の回答を使用することができ、ダイナミックA = T tを使用することができますスイッチを使用してください。

0

本当に良い解決策ですが、IMOは単純に派生リポジトリクラスでメソッドを呼び出していますが、ベースリポジトリでは呼び出されません。次に、派生クラスが照会しているものを知っているので、EmployeesRepositoryが明示的にEmployee.GetFilterを呼び出すため、問題はありません。

関連する問題