我正忙於在Dapper和DapperExtensions上創建封裝擴展方法。此刻,我正在嘗試將過濾添加到GetList<T>
擴展方法中,類似於LINQ的Where<T>
擴展方法。我看過this question,但似乎我無法實現什麼Marc Gravell suggested,因爲.NET 4.5中沒有類型EqualsExpression
。下面是一些演示代碼,以幫助我的問題的解釋:拉開表達式<Func <T, object>>
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq.Expressions;
using DapperExtensions;
namespace Dapper.Extensions.Demo
{
public class Program
{
private static readonly string ConnectionString = ConfigurationManager.ConnectionStrings["DapperDbContext"].ConnectionString;
public static IDbConnection Connection { get { return new SqlConnection(ConnectionString); } }
public static void Main(string[] args)
{
const int marketId = 2;
var matchingPeople = Connection.Get<Person>(p => p.MarketId, marketId); // This works
// Below is a LambdaExpression. expression.Body is, bizarrely, a UnaryExpression with a Convert
//var matchingPeople = Connection.Get<Person>(p => p.MarketId == marketId); // Does not work
foreach (var person in matchingPeople)
{
Console.WriteLine(person);
}
if (Debugger.IsAttached)
Console.ReadLine();
}
}
public static class SqlConnectionExtensions
{
public static IEnumerable<T> Get<T>(this IDbConnection connection, Expression<Func<T, object>> expression, object value = null) where T : class
{
using (connection)
{
connection.Open();
// I want to be able to pass in: t => t.Id == id then:
// Expression<Func<T, object>> expressionOnLeftOfFilterClause = t => t.Id;
// string operator = "==";
// object valueFromLambda = id;
// and call Predicates.Field(expressionOnLeftOfFilterClause, Operator.Eq, valueFromLambda)
var predicate = Predicates.Field(expression, Operator.Eq, value);
var entities = connection.GetList<T>(predicate, commandTimeout: 30);
connection.Close();
return entities;
}
}
}
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public int MarketId { get; set; }
public override string ToString()
{
return string.Format("{0}: {1}, {2} - MarketId: {3}", Id, Surname, FirstName, MarketId);
}
}
}
要特別注意我的Get<T>
擴展方法:當我通過在任一p => p.MarketId
或p => p.MarketId == marketId
,expression.Body
是UnaryExpression
型。對於後者,expression.Body
實際上包含{Convert((p.MarketId == 2))}
。
試圖
var binaryExpression = expression as BinaryExpression;
回報null
,因爲有它,我可以找到有用Left
和Right
特性,這是不幸的。
那麼,有沒有人知道如何實現我想要的?更進一步,我希望能夠根據傳入的lambda表達式來選擇Operator
枚舉。任何幫助將非常感謝。
我的猜測是'UnaryExpression'的'Operand'屬性是'BinaryExpression'你正在尋找。 – Iridium 2013-03-01 09:53:36
@Iridium我認爲你是對的;通過調試,我可以看到'expression.Body'的'Operand'類型爲'LogicalBinaryExpression',但是如何訪問'expression.Body.Operand' in-code?智能感知無法解決這個問題? – 2013-03-01 10:00:47
@Iridium是絕對正確的,現在就試試吧:'BinaryExpression binary =(expr.Body as UnaryExpression).Operand as BinaryExpression;'產生期望的'BinaryExpression'。 @Jon Skeet完全向你解釋爲什麼轉換會出現(值類型被裝箱到'object')......當心你自己可能發送的更復雜的表達式樹。你不能在用戶程序員一方做一個表達式樹解析器,並在庫書寫器端做出非常大的假設...... – 2013-03-01 10:04:14