如何检查扩展方法中的“类型”中是否存在属性
本文关键字:类型 是否 属性 存在 方法 何检查 检查 扩展 | 更新日期: 2023-09-27 18:15:13
我经常有这样的代码:
var stRecs = db.<someTable>
.Where(a => a.DepID == depID)
选择一条记录,但是如果depID == 0
我想要返回所有记录。
我正在考虑创建一个扩展方法"WhereDepID_OrAll",如
public static IQueryable<T> WhereDepID_OrAll<T>(this IQueryable<T> source)
where T: // is what?
{
if(depID > 0) { return source.Where(a => a.depID == depID); }
else return source.Where(a => a);
}
现在我的基本问题是:我有几个表与depID -我如何设置Where T:
?该方法如何确定表是否有depID?
解决潜在问题的更好方法?
乍一看,反应是:创建一个接口
public interface ObjectWithDepartmentInterface {
int depID;
}
使所有使用此depId的实体实现此接口,并使用
where T : ObjectWithDepartmentInterface
但是linq to entities不接受query…基于接口
生成的表达式所以唯一的方法是让你的实体从一个具有depId属性的公共实体(可能是抽象实体)继承一个depId。
并使用这个抽象实体作为
where T:
一种更简单(但更难看)的方法是不给T添加约束,在方法中构建谓词,在糟糕的情况下抛出异常。
if (typeof(T).GetProperty("depId") == null)
throw InvalidOperationException (string.Format("{0}" doesn't have a depId property, typeof(T).Name))
编辑
但也许这不是depId作为共同属性的问题
public static IQueryable<T> WhereExistsOrAll<T>(this IQueryable<T> source, string propertyName, int value)
where T: // is what?
{
if (value == 0)
return source;
var parameter = Expression.Parameter(typeof(T), "m");
Expression member = parameter;
member = Expression.Property(member, propertyName);
member = Expression.Equals(member, Expression.Constant(value));
var lambda = Expression.Lambda<Func<T, bool>>(member, new[]{parameter});
return source.Where(lambda);
}
使用var stRecs = db.<someTable>.WhereExistsOrAll("depId", depId);
编辑2
另一种方法是解析谓词以获得"常量"值
之类的
public static IQueryable<T> GetAllOrRestrict<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> predicate)
{
var expression = predicate.Body as BinaryExpression;
var rightPart = expression.Right as MemberExpression;
var value = GetValue(rightPart);
var test = value.ToString();
int val;
if (Int32.TryParse(value.ToString(), out val))
{
if (val != 0)
return queryable.Where(predicate);
}
return queryable;
}
private static object GetValue(MemberExpression member)
{
var objectMember = Expression.Convert(member, typeof(object));
var getterLambda = Expression.Lambda<Func<object>>(objectMember);
var getter = getterLambda.Compile();
return getter();
}
使用var stRecs = db.<someTable>.GetAllOrRestrict(m => m.depID == depId);
我知道这不是特别时尚,但这不正是实体框架中的查询生成器方法吗?
var stRecs = db.<someTable>
.Where("it.DepID == @depID OR @depID = 0",
new ObjectParameter("depID", depID));
这适用于任何someTable
,这样它就有一个名为DepID
的列。它当然可以是一个扩展方法:
public static ObjectQuery<T> WhereIdEqualOrAll<T>(this ObjectQuery<T> q, int depID)
where T : class
{
return q.Where("it.DepID = @id OR @id = 0", new ObjectParameter("id", id));
}
可以这样调用:
var stRecs = db.<someTable>.WhereIdEqualOrAll(depID);
使用接口:
public interface IInterface
{
int depId;
}
这将强制T
继承IInterface
并实现depId
。
然后你可以把它添加到扩展名:
public static IQueryable<T> WhereDepID_OrAll<T>(this IQueryable<T> source) where T: IInterface
{
}
使用一个接口,然后手动构建一个表达式树,引用实际的类。
Raphaels Edit 2做到了!
小版:如果存在DepID,我如何包含null值?
我喜欢返回ID == x或ID == NULL的所有部门
可能与一个额外的bool包括ullvalues)
public static IQueryable<T> GetAllOrRestrict<T>(this IQueryable<T> queryable,
Expression<Func<T, bool>> predicate,
bool includeNullValues)
{
var expression = predicate.Body as BinaryExpression;
var rightPart = expression.Right as MemberExpression;
var value = GetValue(rightPart);
var test = value.ToString();
int val;
if (Int32.TryParse(value.ToString(), out val))
{
if (val != 0)
{
if (includeNullValues)
{
var parameter = Expression.Parameter(typeof(T),"m");
return queryable.Where(predicate) <====HOW to " || depID == null) ???
}
else
{
return queryable.Where(predicate);
}
}
}
return queryable;
}