Czy można zakodować przypisanie do drzewa wyrażeń?Przypisanie w drzewach wyrażeń .NET 3.5
Odpowiedz
Nie, nie wierzę w to.
pewnością kompilator C# wykluczy go przy konwersji wyrażenia lambda:
int x;
Expression<Func<int,int>> foo = (x=y); // Assign to x and return value
To daje błąd:
CS0832: An expression tree may not contain an assignment operator
Można prawdopodobnie obejść przez nexting wyrażenia drzew. Wywołaj funkcję lambda, gdzie argumentem jest wartość cesjonariusza.
Powinieneś zrobić to z biblioteką .NET 4.0. importując plik Microsoft.Scripting.Core.dll do projektu .NET 3.5.
Używam DLR 0.9 - nie mogą być pewne zmiany na Expession.Block i Expression.Scope w wersji 1.0 (Można zobaczyć referencję http://www.codeplex.com/dlr/Thread/View.aspx?ThreadId=43234)
Po próbka jest pokazać.
using System;
using System.Collections.Generic;
using Microsoft.Scripting.Ast;
using Microsoft.Linq.Expressions;
using System.Reflection;
namespace dlr_sample
{
class Program
{
static void Main(string[] args)
{
List<Expression> statements = new List<Expression>();
ParameterExpression x = Expression.Variable(typeof(int), "r");
ParameterExpression y = Expression.Variable(typeof(int), "y");
statements.Add(
Expression.Assign(
x,
Expression.Constant(1)
)
);
statements.Add(
Expression.Assign(
y,
x
)
);
MethodInfo cw = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
statements.Add(
Expression.Call(
cw,
y
)
);
LambdaExpression lambda = Expression.Lambda(Expression.Scope(Expression.Block(statements), x, y));
lambda.Compile().DynamicInvoke();
Console.ReadLine();
}
}
}
Jak Jon Skeet i TraumaPony już powiedziałem, Expression.Assign
nie jest dostępna przed .NET 4. Oto kolejny konkretny przykład, jak obejść ten brakujący bit:
public static class AssignmentExpression
{
public static Expression Create(Expression left, Expression right)
{
return
Expression.Call(
null,
typeof(AssignmentExpression)
.GetMethod("AssignTo", BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(left.Type),
left,
right);
}
private static void AssignTo<T>(ref T left, T right) // note the 'ref', which is
{ // important when assigning
left = right; // to value types!
}
}
Następnie wystarczy zadzwonić AssignmentExpression.Create()
w miejsce Expression.Assign()
.
Moja metoda rozszerzenie dla robi dokładnie to:
/// <summary>
/// Provides extensions for converting lambda functions into assignment actions
/// </summary>
public static class ExpressionExtenstions
{
/// <summary>
/// Converts a field/property retrieve expression into a field/property assign expression
/// </summary>
/// <typeparam name="TInstance">The type of the instance.</typeparam>
/// <typeparam name="TProp">The type of the prop.</typeparam>
/// <param name="fieldGetter">The field getter.</param>
/// <returns></returns>
public static Expression<Action<TInstance, TProp>> ToFieldAssignExpression<TInstance, TProp>
(
this Expression<Func<TInstance, TProp>> fieldGetter
)
{
if (fieldGetter == null)
throw new ArgumentNullException("fieldGetter");
if (fieldGetter.Parameters.Count != 1 || !(fieldGetter.Body is MemberExpression))
throw new ArgumentException(
@"Input expression must be a single parameter field getter, e.g. g => g._fieldToSet or function(g) g._fieldToSet");
var parms = new[]
{
fieldGetter.Parameters[0],
Expression.Parameter(typeof (TProp), "value")
};
Expression body = Expression.Call(AssignmentHelper<TProp>.MethodInfoSetValue,
new[] {fieldGetter.Body, parms[1]});
return Expression.Lambda<Action<TInstance, TProp>>(body, parms);
}
public static Action<TInstance, TProp> ToFieldAssignment<TInstance, TProp>
(
this Expression<Func<TInstance, TProp>> fieldGetter
)
{
return fieldGetter.ToFieldAssignExpression().Compile();
}
#region Nested type: AssignmentHelper
private class AssignmentHelper<T>
{
internal static readonly MethodInfo MethodInfoSetValue =
typeof (AssignmentHelper<T>).GetMethod("SetValue", BindingFlags.NonPublic | BindingFlags.Static);
private static void SetValue(ref T target, T value)
{
target = value;
}
}
#endregion
}
- 1. Praca z typami zerującymi w drzewach wyrażeń
- 2. Sortowanie Hashset .Net 3.5
- 3. Czy istnieje GUID.TryParse() w .NET 3.5?
- 4. XmlSerializer różni się .NET 3.5 i CF.NET 3.5
- 5. Jak utworzyć zestaw .NET 4.0 w projektach .NET 3.5
- 6. Czy Entity Framework 6 obsługuje .Net 3.5?
- 7. Zmniejszenie aplikacji z .net 4.0 na 3.5
- 8. Czy NUnit działa z .NET 3.5?
- 9. Tworzenie VSPackage kierowania .net 3.5 i 4
- 10. Microsoft .NET 3.5 Pełna wersja do pobrania
- 11. Wymagania wstępne klienta .NET Framework 3.5 SP1
- 12. .NET 3.5 Redystrybucja - 200 MB? Inne opcje?
- 13. Awaria aplikacji po przejściu z .NET 3.5 do .NET 4.0
- 14. Kompatybilność wsteczna .NET Compact 3.5 i 2.0
- 15. WebApi HttpClient dla platformy .NET Framework 3.5
- 16. Korzystanie System.Reactive w .NET 3.5 (w produkcie wysyłki)
- 17. Czy możesz użyć biblioteki .NET 4.0 w projekcie 3.5?
- 18. Wdrażanie funkcji Pub/Sub lub SignalR w .NET 3.5?
- 19. Jak wyświetlić okno dialogowe uwierzytelniania w C# .Net 3.5 SP1
- 20. Jak przekonwertować ciąg na wersję w .net 3.5?
- 21. Pula aplikacji w IIS 7 nie wyświetla .NET Framework 3.5
- 22. Ładowanie XDocument podczas sprawdzania poprawności względem schematu w .NET 3.5
- 23. Czy istnieje sposób emulacji UseLayoutRounding w WPF z .Net 3.5
- 24. Linq + Niepoprawny termin wyrażeń "> '
- 25. C# Metoda dynamiczna - IL vs drzewa wyrażeń
- 26. Jakie są korzyści dla klienta Aktualizacja systemu z .NET 2 do .NET 3.5 lub 4
- 27. ASP.NET 2.0 lub 3.5?
- 28. Łączenie wyrażeń w drzewie wyrażeń
- 29. Jakie NOWE funkcje ma WCF w .NET Framework 4 vs .NET Framework 3.5?
- 30. asp.net 3.5 Żądać zmiennych?
I nie może wydawać się uzyskać to do pracy, czy jest rewizja lub blogu gdzieś? – Maslow