ciklum net sat12112011-alexander fomin-expressions and all, all, all
TRANSCRIPT
Expressions и все-все-все
http://crew.taucraft.com/
http://sane.habrahabr.ru
http://der-waldgeist.blogspot.com
http://twitter.com/AlexSane
http://www.google.com/profiles/shurickFomin
Expression trees…остальные
плюшки
Expression Visitor
2+3*4
2+(3*4)
private static void Main() {
Func<int, int, int> f = (x, y) => x + y;Console.WriteLine(f);
}
System.Func`3[System.Int32,System.Int32,System.Int32]
[CompilerGenerated] private static int <Main>b__0(int x, int y) { return x+y; }
private static void Main() { var f = new Func<int, int, int>(Program.<Main>b__0)); Console.WriteLine(f); }
static void Main() {Expression<Func<int, int, int>> f = (x, y) => x + y;Console.WriteLine(f);
}
(x, y) => (x + y)
ParameterExpression CS0 = Expression.Parameter(typeof (int), "x");ParameterExpression CS1 = Expression.Parameter(typeof (int), "y");Expression<Func<int, int, int>> f =
Expression.Lambda<Func<int, int, int>>( Expression.Add(CS0, CS1), new ParameterExpression[] {CS0, CS1}
);
Expression<Func<DateTime, int>> f = d => (int) Math.Abs((DateTime.Now - d).TotalSeconds);
ParameterExpression CS0 = Expression.Parameter(typeof (DateTime), "d");Expression<Func<DateTime, int>> f =
Expression.Lambda<Func<DateTime, int>>(Expression.Convert(
Expression.Call( null, (MethodInfo) methodof (Math.Abs), new Expression[]{
Expression.Property(Expression.Subtract(
Expression.Property(null, (MethodInfo) methodof (DateTime.get_Now)),CS0,(MethodInfo) methodof (DateTime.op_Subtraction)
),(MethodInfo) methodof (TimeSpan.get_TotalSeconds)
)}
), typeof (int) ), new ParameterExpression[] {CS0} );
d => (int) Math.Abs((DateTime.Now - d).TotalSeconds);
Expression tree
d => (int) Math.Abs((DateTime.Now - d).TotalSeconds);
.NET 3.0
• Operators• Method calls• Property getters• Collection initializers• Object initializers• Convert/Cast• Constants
(x,y)=>x+y
.NET 4.0
• Blocks• Loops• Try/Catch/Finally• Goto/Labels• Variables• Assignments• If/Then/Else
(x,y) => { return x+y; }*
ExpressionVisitor
protected virtual Expression VisitBinary(BinaryExpression b) {
Expression left = this.Visit(b.Left); Expression right = this.Visit(b.Right); return b;
}
protected virtual Expression VisitBinary(BinaryExpression b) {
Expression left = this.Visit(b.Left); Expression right = this.Visit(b.Right); if (left != b.Left || right != b.Right) {
return Expression.MakeBinary(b.NodeType, left, right, b.Method
); } return b;
}
IQueryable<Tree> forest = // ...var queryable = from tree in forest
where tree.HasHollowselect tree.ColectSomeHoney();
var queryable = forest.Where(tree => tree.HasHollow).Select(tree => tree.ColectSomeHoney());
var queryable = Queryable.Select( Queryable.Where(forest, tree => tree.HasHollow),
tree => tree.ColectSomeHoney() );
var queryable = Enumerable.Select( Enumerable.Where(forest.AsEnumerable
(), tree => tree.HasHollow), tree => tree.ColectSomeHoney() );
internal override Expression VisitMethodCall(MethodCallExpression m) {
Expression instance = base.VisitMethodCall(m);if (m.Method.DeclaringType == typeof(Queryable)) {
MethodInfo info = FindEnumerableMethod(m.Method); return Expression.Call(instance, info, source); } return m;
}
internal override Expression VisitMethodCall(MethodCallExpression m) {
Expression instance = base.VisitMethodCall(m);
if (m.Method.DeclaringType == typeof(Queryable)) {
MethodInfo info = FindEnumerableMethod(m.Method); return Expression.Call(instance, info, source); } return m;
}
Compiled expressions
string PasswordPhrase(bool isBear) {
return string.Format("{0} очень любит {1}", isBear ? "Мишка" : "Ослик",
isBear ? "мёд" : "йод"); }
ILGenerator generator = //... var label1 = generator.DefineLabel(); var label2 = generator.DefineLabel(); var label3 = generator.DefineLabel(); var label4 = generator.DefineLabel();generator.Emit(OpCodes.Ldstr, "{0} очень любит {1}"); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Brtrue_S, label1); generator.Emit(OpCodes.Ldstr, "Мишка"); generator.Emit(OpCodes.Br_S, label2);generator.MarkLabel(label1); generator.Emit(OpCodes.Ldstr, ”Ослик"); generator.MarkLabel(label2); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Brtrue_S, label3); generator.MarkLabel(label3); generator.Emit(OpCodes.Ldstr, ”мёд"); generator.Emit(OpCodes.Br_S, label4); generator.Emit(OpCodes.Ldstr, "йод"); generator.MarkLabel(label4);generator.EmitCall(OpCodes.Call, typeof(String).GetMethod("Format"), new[] { typeof(string), typeof(object),
typeof(object) });generator.Emit(OpCodes.Ret);
Func<bool, string> Emit() {
var isBear = Expression.Parameter(typeof (bool), "isBear"); var lambda = Expression.Lambda<Func<bool, string>>( Expression.Call(
Method(() => string.Format("", null, null)),
Expression.Constant("{0} очень любит {1}"),Expression.Condition(isBear,
Expression.Constant("Мишка"),
Expression.Constant("Ослик")), Expression.Condition(isBear, Expression.Constant("мёд"), Expression.Constant("йод") )
));
Func<bool, string> func = lambda.Compile(); return func;
}
Reflection in compile timepublic class Tree {
public Honey ColectSomeHoney() {
//... return new Honey();
} } private static void Main() {
MethodInfo method = typeof(Tree).GetMethod( "ColectSomeHoney",
BindingFlags.Public | BindingFlags.Instance);
}
Reflection in compile timepublic class Tree {
public Honey CollectSomeHoney() { //... return new Honey(); }
} private static void Main() {
MethodInfo method = typeof(Tree).GetMethod( "ColectSomeHoney", BindingFlags.Public | BindingFlags.Instance);
}
Reflection in compile timepublic class Tree {
public Honey CollectSomeHoney() {
//... return new Honey();
} } private static void Main() {
MethodInfo method =
typeof(Tree).GetMethod( "ColectSomeHoney", BindingFlags.Public | BindingFlags.Instance);
}
Reflection in compile timeprivate static void Main() {
var method = GetMethod<Tree>(x => x.ColectSomeHoney()); } public static MethodInfo GetMethod<T>(Expression<Action<T>> e) {
return ((MethodCallExpression) e.Body).Method;
}
Reflection in compile timeprivate static void Main() { var method = GetMethod<Tree>(x => x.CollectSomeHoney()); } public static MethodInfo GetMethod<T>(Expression<Action<T>> e) {
return ((MethodCallExpression) e.Body).Method;
}
IQueryableinterface IQueryable<T> : IEnumerable<T> , IQueryable{
Type ElementType { get; }Expression Expression { get; } IQueryProvider Provider { get; }
}
interface IQueryProvider{
IQueryable CreateQuery(Expression e) ;IQueryable<T> CreateQuery<T> (Expression e);object Execute (Expression expression); object Execute (Expression expression);
}
IQueryable
Expressions в C# — impress yourself!
http://habrahabr.ru/blogs/net/83169/
LINQ: Building an IQueryable provider series
http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx
Винни-Пух и Все-Все-все
ISBN: 978-5-17-064151-2