Ich bin beschäftigt Erstellen von Wrapper-Erweiterung Methoden auf Dapper und DapperExtensions. Im Moment versuche ich, der Erweiterungsmethode GetList<T>
eine Filterung hinzuzufügen, ähnlich der LINQ-Erweiterungsmethode Where<T>
. Ich habe this question gesehen, aber es scheint, ich kann nicht implementieren, was Marc Gravell suggested, weil es keinen Typ EqualsExpression
in .NET 4.5 gibt. Hier finden Sie einige Demo-Code mit der Erklärung meines Problems zu helfen:Auseinanderziehen Ausdruck <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);
}
}
}
besondere Berücksichtigung meiner Get<T>
Extension-Methode: Wenn ich entweder passieren in p => p.MarketId
oder p => p.MarketId == marketId
, expression.Body
ist vom Typ UnaryExpression
. Für Letzteres enthält expression.Body
tatsächlich {Convert((p.MarketId == 2))}
.
Versuch
var binaryExpression = expression as BinaryExpression;
kehrt null
, was schade ist, denn es gibt Left
und Right
Eigenschaften, die ich nützlich gefunden haben könnte.
Also, weiß jemand, wie man erreicht, was ich will? Weiter unten möchte ich in der Lage sein, die Operator
enum basierend auf dem Lambda-Ausdruck auszuwählen, die übergeben wurde. Jede Hilfe würde sehr geschätzt werden.
Meine Vermutung wäre, dass die 'Operand' Eigenschaft der' UnaryExpression' die 'BinaryExpression' ist, die Sie suchen. – Iridium
@Iridium Ich denke du hast recht; durch Debugging kann ich sehen, dass der 'Operand' von' expression.Body' vom Typ 'LogicalBinaryExpression' ist, aber wie kann ich auf 'expression.Body.Operand' in-code zugreifen? Intellisense kann das nicht lösen? –
@Iridium ist absolut richtig, gerade versucht es jetzt: 'BinaryExpression binary = (expr.Body als UnaryExpression) .Operand als BinaryExpression;' ergibt die viel gewünschte 'BinaryExpression'. @ Jon Skeet erklärte Ihnen genau, warum die Konvertierung erscheint (Werttypen werden in "Objekt" eingerahmt) ... Vorsicht vor noch komplexeren Ausdrucksbäumen, die Sie selbst vielleicht selbst senden. Sie können nicht einen Ausdruck Baum Parser, der ein hohes Spektrum an Möglichkeiten auf der Seite des Benutzers Programmierer hat und sehr große Annahmen auf der Bibliothek Writer Seite ... –