数据权限过滤,一个关于特性,泛型及IQueryable的问题

coudoufu 2013-09-07 01:25:49
我的数据访问是基于Entity Framework的,需要做数据权限过滤,我使用Unity AOP来做,于是写了标记为需要数据权限过滤的特性(用于业务层的方法上)及劫持的Hanlder,我所劫持的这些查询方法返回都是IQueryable<T>类型,这样为了在劫持方法里加上过滤的Lambda表达式以对查询结果进行再次过滤,我的劫持类必须是泛型的,这样导致特性也必须泛型,但是特性是不支持泛型的,所以我的问题是不用泛型特性,我的T怎么传进去?因为IQueryable要再次过滤,一定是泛型的。

特性类代码如下:
/// <summary>
/// 问题在于特性不能使用泛型,这里的BaseLimitEntity是model的基类型,包含需要过滤的属性。
/// </summary>
/// <typeparam name="T"></typeparam>
public class DataFilterAttribute<T> : HandlerAttribute where T : BaseLimitEntity
{
public string HospitalIds { get; set; }

public int Order { get; set; } // 这是ICallHandler的成员,表示执行顺序

public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
{
// 不用泛型的话,问题是这里怎么传T进去?
return new DataFilterHandler<T>(Order, HospitalIds);
}
}


劫持类代码如下:
public class DataFilterHandler<T> : ICallHandler where T : BaseLimitEntity 
{
public string HospitalIds { get; set; }

public int Order { get; set; } // 这是ICallHandler的成员,表示执行顺序

private IList<int> hospitalIds;

public DataFilterHandler(int order, string hospitalIds)
{
this.Order = order;
this.HospitalIds = hospitalIds;

this.hospitalIds = new List<int>();
string[] ids = hospitalIds.Split(new char[1] { ',' });
foreach (string id in ids)
{
this.hospitalIds.Add(Convert.ToInt32(id));
}
}

public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
// 调用被劫持的方法,返回的类型是IQueryable<T>
var returnValue = getNext()(input, getNext);

// 进行数据权限过滤
IQueryable<T> query = (IQueryable<T>)returnValue.ReturnValue;
returnValue.ReturnValue = query.Where(e => hospitalIds.Contains(e.HospitalId)).AsQueryable();

return returnValue;
}
}


我要劫持的查询方法格式如下:
[DataFilter(HospitalIds = "2,3", Order = 1)]
IQueryable<T> FindAll (Expression<Func<T, bool>> filter);
...全文
230 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
coudoufu 2013-09-07
  • 打赏
  • 举报
回复
问题解决了,结贴。
coudoufu 2013-09-07
  • 打赏
  • 举报
回复
引用 9 楼 hdhai9451 的回复:
所劫持的这些查询方法返回都是IQueryable<T>类型? --------------------------------- 为何不定义类,返回一个list,这样你想获以什么值都行
因为我要劫持返回的IQueryable后再次进行权限过滤,然后返回给调用业务的地方。
Andy__Huang 2013-09-07
  • 打赏
  • 举报
回复
所劫持的这些查询方法返回都是IQueryable<T>类型? --------------------------------- 为何不定义类,返回一个list,这样你想获以什么值都行
coudoufu 2013-09-07
  • 打赏
  • 举报
回复
引用 7 楼 caozhy 的回复:
反正没办法在attribute上用到泛型,因为泛型是运行时产生的,而attribute是编译的时候写死进去的。 泛型从某种程度上来说不是必须的,所有泛型能做到的事情,用反射一样可以做到。这也是C# 1.x没有泛型,只是不方便而已,并没有什么做不到的原因——C# 1.0可以办到C# 5.0办到的全部的事情。
呵呵,多谢!我试试,有不清楚的再请教。
threenewbee 2013-09-07
  • 打赏
  • 举报
回复
反正没办法在attribute上用到泛型,因为泛型是运行时产生的,而attribute是编译的时候写死进去的。 泛型从某种程度上来说不是必须的,所有泛型能做到的事情,用反射一样可以做到。这也是C# 1.x没有泛型,只是不方便而已,并没有什么做不到的原因——C# 1.0可以办到C# 5.0办到的全部的事情。
threenewbee 2013-09-07
  • 打赏
  • 举报
回复
然后再Activator.CreateInstance
threenewbee 2013-09-07
  • 打赏
  • 举报
回复
反射 MakeGenericType http://msdn.microsoft.com/zh-cn/library/system.type.makegenerictype.aspx
coudoufu 2013-09-07
  • 打赏
  • 举报
回复
引用 1 楼 caozhy 的回复:
传Type 所以你看到很多attribute使用的时候都总是typeof(xxx)来typeof(xxx)去的。
问题是查询那里该怎么写呢?
coudoufu 2013-09-07
  • 打赏
  • 举报
回复
引用 1 楼 caozhy 的回复:
传Type 所以你看到很多attribute使用的时候都总是typeof(xxx)来typeof(xxx)去的。
这个我也有想到,但是 IQueryable<T> query = (IQueryable<T>)returnValue.ReturnValue; returnValue.ReturnValue = query.Where(e => hospitalIds.Contains(e.HospitalId)).AsQueryable(); 这个地方怎么用这个Type呢?首先这个T必须是BaseLimitEntity的继承类才能用HospitalId进行过滤。我也可以写Expression通过类型进行动态过滤,但是过滤的对象一定得是泛型的IQueryable啊。
threenewbee 2013-09-07
  • 打赏
  • 举报
回复
随便找一个 http://msdn.microsoft.com/zh-cn/library/system.windows.point.aspx
[SerializableAttribute]
[TypeConverterAttribute(typeof(PointConverter))]
public struct Point : IFormattable
{
   ...
}
这种在attribute中传type的例子太多了。
threenewbee 2013-09-07
  • 打赏
  • 举报
回复
传Type 所以你看到很多attribute使用的时候都总是typeof(xxx)来typeof(xxx)去的。

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧