c# - 如何检查扩展方法中类型中是否存在属性?

标签 c# linq extension-methods

我经常有这样的代码:

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?

解决根本问题的更好方法?

最佳答案

乍一看, react 是:创建一个接口(interface)

public interface ObjectWithDepartmentInterface {
    int depID;
}

让所有使用这个depId的实体实现这个接口(interface),并使用

where T : ObjectWithDepartmentInterface

但 linq to entities 不接受查询中接口(interface)的属性...参见示例:Expression generated based on interface

因此,唯一的方法是使您的实体具有从具有 depId 属性的公共(public)实体(可能是抽象的)继承的 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)属性的问题 然后

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);

关于c# - 如何检查扩展方法中类型中是否存在属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16730824/

相关文章:

c# - 使用 Task.WaitAll(threads) 没有适本地阻塞

c# - ASP.NET C# 在 SQL Server 数据库表中搜索

c# - 将 SqlDataReader 转换为 linq 表达式

c# - yield 模式,状态机流程

c# - 为什么我们在 LINQ 中需要 Single()?

c# - 使用最小起订量的扩展方法的单元测试

c# - 使用 Umbraco Base 返回 Json 而不是 XML

c# - 无法等待'int'异步/等待C#

c# - 带有选择非重复计数的 EF Core GroupBy

c# - 匿名类型 - 是否有任何显着特征?