Sto cercando di ottenere un valore da unottenere un valore da un ConstantExpression
var guid = Guid.Parse("SOMEGUID-GUID-GUID-GUID-SOMEGUIDGUID");
Expression<Func<Someobject, bool>> selector = x => x.SomeId == guid;
Per gli scopi di registrazione ho bisogno di essere in grado di pesce che guid.
Ho provato il seguente codice, che ritengo un po 'vicino a quello che sto cercando, ma non del tutto.
BinaryExpression binaryExpression = (BinaryExpression)selector.Body;
MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand;
ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
Ora, ConstantExpression espone un membro di 'Valore', che contiene quello che sto cercando, ma io sono un po 'perplesso come estrarre in realtà questo.
E no:
var val = (Guid)constantExpression.Value;
non funziona :)
risolto
Il risultato finale assomiglia a:
BinaryExpression binaryExpression = (BinaryExpression)selector.Body;
MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand;
var myGuid = Expression.Lambda(memberExpression).Compile().DynamicInvoke();
Follow-up
ho fatto dei test di velocità rudementary utilizzando il codice seguente:
static void Main(string[] args)
{
var id = Guid.Parse("bleh");
Expression<Func<Thingemebob, bool>> selector = x => x.Id == id;
var tickList = new List<long>();
for (int i = 0; i < 100000; i++)
{
var sw = Stopwatch.StartNew();
GetValueWithExpressionsAndReflection(selector);
sw.Stop();
tickList.Add(sw.ElapsedTicks);
}
Trace.WriteLine("GetValueWithExpressionsAndReflection: Average over 100000, first call included: " + tickList.Average());
Trace.WriteLine("GetValueWithExpressionsAndReflection: First call: " + tickList[0]);
Trace.WriteLine("GetValueWithExpressionsAndReflection: Average over 100000, first call excluded: " + tickList.Skip(1).Average());
tickList = new List<long>();
for (int i = 0; i < 100000; i++)
{
var sw = Stopwatch.StartNew();
GetValueWithCompiledExpression(selector);
sw.Stop();
tickList.Add(sw.ElapsedTicks);
}
Trace.WriteLine("GetValueWithCompiledExpression: Average over 100000, first call included: " + tickList.Average());
Trace.WriteLine("GetValueWithCompiledExpression: First call: " + tickList[0]);
Trace.WriteLine("GetValueWithCompiledExpression: Average over 100000, first call excluded: " + tickList.Skip(1).Average());
Debugger.Break();
}
private static void GetValueWithCompiledExpression(Expression<Func<Note, bool>> selector)
{
BinaryExpression binaryExpression = (BinaryExpression)selector.Body;
MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand;
var o = Expression.Lambda(memberExpression).Compile().DynamicInvoke();
}
private static void GetValueWithExpressionsAndReflection(Expression<Func<Note, bool>> selector)
{
BinaryExpression binaryExpression = (BinaryExpression)selector.Body;
MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand;
ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
FieldInfo member = (FieldInfo)memberExpression.Member;
var instance = constantExpression.Value;
var guid = member.GetValue(instance);
}
Attiva la versione di compilazione è molto più lento. Stiamo osservando un'enorme differenza. (Timing è in tick):
GetValueWithExpressionsAndReflection: Media su 100000, prima chiamata comprese 0,93122
GetValueWithExpressionsAndReflection: Primo bando: 851
GetValueWithExpressionsAndReflection: Media su 100000, prima chiamata esclusi: 0,922719227192272
Versus:
GetValueWithCompiledExpression: Media su 100000, prima chiamata incluso: 499,53669
GetValueWithCompiledExpression: Prima convocazione: 16818
GetValueWithCompiledExpression: Media su 100000, prima chiamata esclusa: 499,373503735037
Test di livello o no: senza dubbio userò la versione di riflessione. miei risultati sembrano essere coerenti con: http://www.minddriven.de/index.php/technology/dot-net/c-sharp/efficient-expression-values
Dal tuo primo frammento di codice sembra che tu non abbia 'Guid' ma' stringa', se non sei _ sicuro del suo formato puoi anche solo usare i metodi di classe 'Convertitore'. –
Qual è il valore di constantExpression.Value.GetType() e cosa ti dice? – usr
@AdrianoRepetti Sono molto sicuro del formato, ho aggiornato la domanda per riflettere questo più correttamente. EFAndExpressions.Program + <> c__DisplayClass0, che al momento non mi dice nulla :) – Apeiron