How to get Property Wert von MemberExpression ohne .Compile()?
Habe ich Probleme, versuchen, den Wert eines Objekts aus dem Expression Tree ohne Verwendung .Compile()
Das Objekt ist ganz einfach.
var userModel = new UserModel { Email = "[email protected]"};
Die Methode geben wird, mich zu Fragen, wie es aussieht.
private void VisitMemberAccess(MemberExpression expression, MemberExpression left)
{
var key = left != null ? left.Member.Name : expression.Member.Name;
if (expression.Expression.NodeType.ToString() == "Parameter")
{
//add the string key
_strings.Add(string.Format("[{0}]", key));
}
else
{
//add the string parameter
_strings.Add(string.Format("@{0}", key));
//Potential NullReferenceException
var val = (expression.Member as FieldInfo).GetValue((expression.Expression as ConstantExpression).Value);
//add parameter value
Parameters.Add("@" + key, val);
}
}
Den tests, die ich laufen gehe, sind Recht einfach
[Test] //PASS
public void ShouldVisitExpressionByGuidObject ()
{
//Setup
var id = new Guid( "CCAF57D9-88A4-4DCD-87C7-DB875E0D4E66" );
const string expectedString = "[Id] = @Id";
var expectedParameters = new Dictionary<string, object> { { "@Id", id } };
//Execute
var actualExpression = TestExpression<UserModel>( u => u.Id == id );
var actualParameters = actualExpression.Parameters;
var actualString = actualExpression.WhereExpression;
//Test
Assert.AreEqual( expectedString, actualString );
CollectionAssert.AreEquivalent( expectedParameters, actualParameters );
}
[Test] //FAIL [System.NullReferenceException : Object reference not set to an instance of an object.]
public void ShouldVisitExpressionByStringObject ()
{
//Setup
var expectedUser = new UserModel {Email = "[email protected]"};
const string expectedString = "[Email] = @Email";
var expectedParameters = new Dictionary<string, object> { { "@Email", expectedUser.Email } };
//Execute
var actualExpression = TestExpression<UserModel>( u => u.Email == expectedUser.Email );
var actualParameters = actualExpression.Parameters;
var actualString = actualExpression.WhereExpression;
//Assert
Assert.AreEqual( expectedString, actualString );
CollectionAssert.AreEquivalent( expectedParameters, actualParameters );
}
Sollte ich beachten Sie, dass änderungen
var val = (expression.Member as FieldInfo).GetValue((expression.Expression as ConstantExpression).Value);
zu
var val = Expression.Lambda( expression ).Compile().DynamicInvoke().ToString();
erlauben wird, den test zu bestehen, aber diesen code ausführen muss, um auf iOS, und kann daher nicht verwenden .Compile()
- Ist
UserModel.Email
wirklich ein Feld? Oder ist es eine Eigenschaft? - Wenn es eine Eigenschaft dann
expression
ist PropertyExpression -> FieldExpression -> ConstantExpression, wenn der code übernimmt nur FieldExpression -> ConstantExpression-daher das problem. - Ah, das macht Sinn... laß mich sehen, was ich mit kommen.
- danke @svick, du hast Recht. Es stolpert auf dem Feld, wenn es tatsächlich eine Eigenschaft.
- das war ein Abenteuer in Geduld, um den Wert einer Immobilie. Es ist nicht annähernd so intuitiv wie ein Feld.
Du musst angemeldet sein, um einen Kommentar abzugeben.
TLDR;
Reflexion ist ok zu verwenden, solange Sie Sie nicht verwenden
Emit
oderCompile
. In der Frage, der Wert wird extrahiertFieldInfo
, aber es wird nicht extrahiertPropertyInfo
. Stellen Sie sicher, Sie können BEIDES.Long-winded-version
So die Kommentare wies mich in die richtige Richtung. Ich kämpfte etwas mit dem bekommen der PropertyInfo, aber am Ende, hier ist was ich kam mit.
Im wesentlichen, wenn die
Member.NodeType
ist einParameter
, dann werde ich es als SQL-Feld.[FieldName]
Sonst verwende ich es als SQL-Parameter
@FieldName
... rückwärts, die ich kenne.Wenn die
Member.NodeType
ist KEIN Parameter, dann kann ich überprüfen, um zu sehen, ob es entweder ein ModellField
oder ein ModellProperty
. Von dort aus, bekomme ich den gewünschten Wert aus, und fügen Sie den Schlüssel/Wert-Paaren in ein Dictionary verwendet werden, die als SQL-Parameter.Das Endergebnis ist, dass ich erstellen Sie eine Zeichenfolge, die aussieht wie
Dann die Parameter übergeben werden