원본 : https://github.com/pjc0247/LinqExpressionSnippets
LinqExpressionSnippets
System.Linq.Expression
네임스페이스 아래의 기능들에 대한 복붙용 코드 조각들.
Lambda를 Expression으로 전달받기
람다의 타입 판별
public static void Foo<T>(Expression<Func<T>> f)
{
// Foo(() => Math.Abs(1));
if (f.Body is MethodCallExpression)
Console.WriteLine("MethodCallExpression");
// Foo(() => pos.x);
if (f.Body is MemberExpression)
Console.WriteLine("MemberExpression");
// Foo(() => 10);
if (f.Body is ConstantExpression)
Console.WriteLine("ConstExpression");
// Foo(() => a > b);
if (f.Body is BinaryExpression)
Console.WriteLine("BinaryExpression");
}
MethodCallExpression
// Foo(() => Math.Abs(1));
if (f.Body is MethodCallExpression)
{
var body = f.Body as MethodCallExpression;
// System.Math
Console.WriteLine(body.Method.DeclaringType);
// Abs
Console.WriteLine(body.Method.Name);
// 1
Console.WriteLine(body.Arguments[0]);
}
MemberExpression
// Foo(() => pos.x);
if (f.Body is MemberExpression)
{
var body = f.Body as MemberExpression;
// Vector2
Console.WriteLine(body.Member.DeclaringType);
var fieldExp = (MemberExpression)body.Expression;
// pos
Console.WriteLine(fieldExp.Member.Name);
// System.Int32
Console.WriteLine(body.Type);
// x
Console.WriteLine(body.Member.Name);
}
ConstantExpression
// Foo(() => 10);
if (f.Body is ConstantExpression)
{
var body = f.Body as ConstantExpression;
// System.Int32
Console.WriteLine(body.Type);
// 10
Console.WriteLine(body.Value);
}
BinaryExpression
// Foo(() => a > b);
if (f.Body is BinaryExpression)
{
var body = f.Body as BinaryExpression;
// Expression
Console.WriteLine(body.Left);
// Expression
Console.WriteLine(body.Right);
// ExpressionType.GreaterThan
Console.WriteLine(body.NodeType);
}
Exression 트리 생성하기
Hello World
var exp = Expression.Block(
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("Hello World")
));
var lambda = Expression.Lambda<Action>(exp);
lambda.Compile()();
local variables
var loc1 = Expression.Variable(typeof(int));
var loc2 = Expression.Variable(typeof(int));
var exp = Expression.Block(
// 지역 변수 선언
new ParameterExpression[] {
loc1, loc2
},
// 메소드 바디
Expression.Assign(
loc1,
Expression.Constant(10)),
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) }),
loc1
));
var lambda = Expression.Lambda<Action>(exp);
lambda.Compile()();
If ~ Else
var loc1 = Expression.Variable(typeof(int));
var loc2 = Expression.Variable(typeof(int));
var exp = Expression.Block(
// 지역 변수 선언
new ParameterExpression[] {
loc1, loc2
},
// 메소드 바디
Expression.Assign(
loc1,
Expression.Constant(11)),
Expression.IfThenElse(
Expression.Equal(loc1, Expression.Constant(10)),
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("loc1 is 10")),
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("loc1 is not 10"))
));
var lambda = Expression.Lambda<Action>(exp);
lambda.Compile()();
트리 끼워넣기(Injection)
Before, After
static void Zoo(Expression<Action> f)
{
var exp = Expression.Block(
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("before `f`")),
f.Body,
Expression.Call(
null,
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),
Expression.Constant("after `f`"))
);
var lambda = Expression.Lambda<Action>(exp);
lambda.Compile()();
}
트리 순회하기
static void Rini(Expression f)
{
Console.WriteLine(f);
if (f is MethodCallExpression)
{
var body = f as MethodCallExpression;
foreach (var arg in body.Arguments)
Rini(arg);
}
if (f is BinaryExpression)
{
var body = f as BinaryExpression;
Rini(body.Left);
Rini(body.Right);
}
}
static void Rini(Expression<Action> f)
{
Rini(f.Body);
}
Expression
은 순회와, 수정에 적합한 구조는 아닙ㄴㅣ디ㅏ.
'C#' 카테고리의 다른 글
[C#] Async,Await의 내부 (0) | 2016.08.29 |
---|---|
[C#] async void / Task (0) | 2016.07.18 |
[HTTP] 웹소켓 핸드쉐이킹 (2) | 2016.06.28 |
[C#] Mono 환경인지 구분하기 (0) | 2016.06.21 |
[NUnit] Callback 방식의 API 테스트하기 (1) | 2016.06.16 |