식 나무의 동적 생성 결과를 디버깅하기 위해 우리 취재반은 남미 아마존으로 날아갔다.
15095 단어 dnSpy.NETFrameworkC#.NET
IL Spy도 DASM도 할 수 없었던 것
ExpresionTree를 이용한 동적인 메소드 구축의 결과를 디컴파일하려고 했을 경우, IL Spy를 사용해도 DASM을 사용해도 일근줄로는 가지 않는다.
왜냐하면, 프로그램을 컴파일해 어셈블리를 생성한 시점이라면, 그 어셈블리 중에는 ExpressioTree 그 자체인가, ExpressionTree를 구축하기 위한 코드가 컴파일 되고 있는 것만으로 생성 결과는 당연히 런타임까지 존재하지 않을 수 없다 .
그래서, 그 소스 코드나 ExoressionTree 등을 표시하는 것은 가능하더라도 그 컴파일 결과를 디컴파일하는 것은 꽤 귀찮은 일이었다.
그런 가운데, 우리 취재반은 dnSpy를 사용하는 것으로 이 ExpressionTree의 동적 생성 결과를 디컴파일은 커녕, 디버그조차 가능하다는 정보를 잡아 일로 남미 아마존으로 날아갔다.
dnSpy를 사용해 보았습니다.
dnSpy 단독으로 어제 쓴 대로 디버그가 가능해지고 있다. 디버깅할 수 있다고 하는 것은 대상 어셈블리를 dnSpy 안에서 실행 가능하다고 하는 것이기 때문에, 아무것도 생각하지 않고 Compile 메소드를 통해 실행하면 스텝 인 할 수 있지? 그리고 달콤한 생각을 가지고 시도했습니다.
using System;
using System.Linq.Expressions;
namespace GoAmazon
{
class Program
{
static void Main(string[] args)
{
Expression<Action> expr = () => Console.WriteLine("我々取材班は南米アマゾンへと飛んだ!");
Action act = expr.Compile();
act();
}
}
}
이것을 dnSpy에 먹여 디버그 해 보니 동적으로 컴파일되었다 act
오치였다.
테나 코토에서 결국 스텝인 할 수 없다는 것은 내용을 긁어 열 수가 없을까 예측을 세웠다.
어떻게 든
이러한 결과에서 런타임에 DynamicAssembly로 올려 버리면 어떻게 될까 생각했을 때 dnSpy의 readme
Set breakpoints in any assembly, including framework assemblies, assemblies in the GAC and assemblies existing only in memory
그리고 있었기 때문에 Assembly는 메모리에 존재하는 것만으로 갈 수 있지 않습니까? 라고 하는 것으로, 헬퍼 만들어 시험해 보았다.
using System;
using System.Linq.Expressions;
namespace GoAmazon
{
class Program
{
static void Main(string[] args)
{
Expression<Func<int, int, int>> addExpr = (x, y) => x + y;
ExpressionHelper.CreateDebugHelper(addExpr).Run(10, 20);
Expression<Action> goAmazon = () => Console.WriteLine("我々取材班は南米アマゾンへと飛んだ!");
ExpressionHelper.CreateDebugHelper(goAmazon).Run();
}
}
}
이런 느낌으로 쓰고 컴파일한 물건을 dnSpy에 먹이게 한다. 먹인 직후가 이하
Expression이 전개되고 있지만, 그 근처는 무시하고, 우선 디버그 해 본다
기본값은 엔트리 포인트에서 중단되므로 Continue를 우선 Click!
그렇다면 방금 전까지 할 수 없었던 ExpressionTree의 결과를 디 컴파일하고 디버깅 할 수 있습니다.
씨앗과 장치
씨앗과 장치는 다음과 같습니다.
using System;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
namespace GoAmazon
{
public abstract class ExpressionHelper
{
protected static readonly MethodInfo BreakInfo = typeof(Debugger).GetMethod("Break");
public static ExpressionHelper<TDelegate> CreateDebugHelper<TDelegate>(Expression<TDelegate> expression) where TDelegate:class=>
new ExpressionHelper<TDelegate>(expression);
}
public class ExpressionHelper<TDelegate> : ExpressionHelper where TDelegate : class
{
internal ExpressionHelper(Expression<TDelegate> expression)
{
(Type[] parameterTypes, Type returnType) getInfo()
{
var tmp = typeof(TDelegate).GetMethod("Invoke");
return (tmp.GetParameters().Select(p => p.ParameterType).ToArray(), tmp.ReturnType);
}
Expression<TDelegate> addBreakPoint()
{
var breakExpr = Expression.Call(BreakInfo);
var blockExpr = Expression.Block(breakExpr, Expression.Invoke(expression, expression.Parameters));
return Expression.Lambda<TDelegate>(blockExpr, expression.Parameters);
}
var asmBld =
AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()),
AssemblyBuilderAccess.RunAndCollect);
var modBld = asmBld.DefineDynamicModule("DynamicallyModule");
var typeBld = modBld.DefineType("Dependence");
var delegateInfo = getInfo();
var methodBld = typeBld.DefineMethod("Target", MethodAttributes.Static | MethodAttributes.Public,
delegateInfo.returnType, delegateInfo.parameterTypes);
addBreakPoint().CompileToMethod(methodBld);
var type = typeBld.CreateType();
Run = type.GetMethod("Target").CreateDelegate(typeof(TDelegate)) as TDelegate;
}
public TDelegate Run { get; }
}
}
자꾸 말하면, 동적으로 어셈블리 모듈 타입 메소드를 쭉 올리고 있다.
그때 받은 Expression을 바탕으로 Debugger.Break()
요약
한 번에 남미 아마존까지 날아가면 우선 디버깅할 수 있었다(`・ω・´)
도우미의 내용은 그 중 마음이 가면 다시 씁니다.
Reference
이 문제에 관하여(식 나무의 동적 생성 결과를 디버깅하기 위해 우리 취재반은 남미 아마존으로 날아갔다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Tokeiya/items/5fd5cef5def7ff440f6d
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
dnSpy 단독으로 어제 쓴 대로 디버그가 가능해지고 있다. 디버깅할 수 있다고 하는 것은 대상 어셈블리를 dnSpy 안에서 실행 가능하다고 하는 것이기 때문에, 아무것도 생각하지 않고 Compile 메소드를 통해 실행하면 스텝 인 할 수 있지? 그리고 달콤한 생각을 가지고 시도했습니다.
using System;
using System.Linq.Expressions;
namespace GoAmazon
{
class Program
{
static void Main(string[] args)
{
Expression<Action> expr = () => Console.WriteLine("我々取材班は南米アマゾンへと飛んだ!");
Action act = expr.Compile();
act();
}
}
}
이것을 dnSpy에 먹여 디버그 해 보니 동적으로 컴파일되었다
act
오치였다.테나 코토에서 결국 스텝인 할 수 없다는 것은 내용을 긁어 열 수가 없을까 예측을 세웠다.
어떻게 든
이러한 결과에서 런타임에 DynamicAssembly로 올려 버리면 어떻게 될까 생각했을 때 dnSpy의 readme
Set breakpoints in any assembly, including framework assemblies, assemblies in the GAC and assemblies existing only in memory
그리고 있었기 때문에 Assembly는 메모리에 존재하는 것만으로 갈 수 있지 않습니까? 라고 하는 것으로, 헬퍼 만들어 시험해 보았다.
using System;
using System.Linq.Expressions;
namespace GoAmazon
{
class Program
{
static void Main(string[] args)
{
Expression<Func<int, int, int>> addExpr = (x, y) => x + y;
ExpressionHelper.CreateDebugHelper(addExpr).Run(10, 20);
Expression<Action> goAmazon = () => Console.WriteLine("我々取材班は南米アマゾンへと飛んだ!");
ExpressionHelper.CreateDebugHelper(goAmazon).Run();
}
}
}
이런 느낌으로 쓰고 컴파일한 물건을 dnSpy에 먹이게 한다. 먹인 직후가 이하
Expression이 전개되고 있지만, 그 근처는 무시하고, 우선 디버그 해 본다
기본값은 엔트리 포인트에서 중단되므로 Continue를 우선 Click!
그렇다면 방금 전까지 할 수 없었던 ExpressionTree의 결과를 디 컴파일하고 디버깅 할 수 있습니다.
씨앗과 장치
씨앗과 장치는 다음과 같습니다.
using System;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
namespace GoAmazon
{
public abstract class ExpressionHelper
{
protected static readonly MethodInfo BreakInfo = typeof(Debugger).GetMethod("Break");
public static ExpressionHelper<TDelegate> CreateDebugHelper<TDelegate>(Expression<TDelegate> expression) where TDelegate:class=>
new ExpressionHelper<TDelegate>(expression);
}
public class ExpressionHelper<TDelegate> : ExpressionHelper where TDelegate : class
{
internal ExpressionHelper(Expression<TDelegate> expression)
{
(Type[] parameterTypes, Type returnType) getInfo()
{
var tmp = typeof(TDelegate).GetMethod("Invoke");
return (tmp.GetParameters().Select(p => p.ParameterType).ToArray(), tmp.ReturnType);
}
Expression<TDelegate> addBreakPoint()
{
var breakExpr = Expression.Call(BreakInfo);
var blockExpr = Expression.Block(breakExpr, Expression.Invoke(expression, expression.Parameters));
return Expression.Lambda<TDelegate>(blockExpr, expression.Parameters);
}
var asmBld =
AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()),
AssemblyBuilderAccess.RunAndCollect);
var modBld = asmBld.DefineDynamicModule("DynamicallyModule");
var typeBld = modBld.DefineType("Dependence");
var delegateInfo = getInfo();
var methodBld = typeBld.DefineMethod("Target", MethodAttributes.Static | MethodAttributes.Public,
delegateInfo.returnType, delegateInfo.parameterTypes);
addBreakPoint().CompileToMethod(methodBld);
var type = typeBld.CreateType();
Run = type.GetMethod("Target").CreateDelegate(typeof(TDelegate)) as TDelegate;
}
public TDelegate Run { get; }
}
}
자꾸 말하면, 동적으로 어셈블리 모듈 타입 메소드를 쭉 올리고 있다.
그때 받은 Expression을 바탕으로 Debugger.Break()
요약
한 번에 남미 아마존까지 날아가면 우선 디버깅할 수 있었다(`・ω・´)
도우미의 내용은 그 중 마음이 가면 다시 씁니다.
Reference
이 문제에 관하여(식 나무의 동적 생성 결과를 디버깅하기 위해 우리 취재반은 남미 아마존으로 날아갔다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Tokeiya/items/5fd5cef5def7ff440f6d
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
using System;
using System.Linq.Expressions;
namespace GoAmazon
{
class Program
{
static void Main(string[] args)
{
Expression<Func<int, int, int>> addExpr = (x, y) => x + y;
ExpressionHelper.CreateDebugHelper(addExpr).Run(10, 20);
Expression<Action> goAmazon = () => Console.WriteLine("我々取材班は南米アマゾンへと飛んだ!");
ExpressionHelper.CreateDebugHelper(goAmazon).Run();
}
}
}
씨앗과 장치는 다음과 같습니다.
using System;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
namespace GoAmazon
{
public abstract class ExpressionHelper
{
protected static readonly MethodInfo BreakInfo = typeof(Debugger).GetMethod("Break");
public static ExpressionHelper<TDelegate> CreateDebugHelper<TDelegate>(Expression<TDelegate> expression) where TDelegate:class=>
new ExpressionHelper<TDelegate>(expression);
}
public class ExpressionHelper<TDelegate> : ExpressionHelper where TDelegate : class
{
internal ExpressionHelper(Expression<TDelegate> expression)
{
(Type[] parameterTypes, Type returnType) getInfo()
{
var tmp = typeof(TDelegate).GetMethod("Invoke");
return (tmp.GetParameters().Select(p => p.ParameterType).ToArray(), tmp.ReturnType);
}
Expression<TDelegate> addBreakPoint()
{
var breakExpr = Expression.Call(BreakInfo);
var blockExpr = Expression.Block(breakExpr, Expression.Invoke(expression, expression.Parameters));
return Expression.Lambda<TDelegate>(blockExpr, expression.Parameters);
}
var asmBld =
AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()),
AssemblyBuilderAccess.RunAndCollect);
var modBld = asmBld.DefineDynamicModule("DynamicallyModule");
var typeBld = modBld.DefineType("Dependence");
var delegateInfo = getInfo();
var methodBld = typeBld.DefineMethod("Target", MethodAttributes.Static | MethodAttributes.Public,
delegateInfo.returnType, delegateInfo.parameterTypes);
addBreakPoint().CompileToMethod(methodBld);
var type = typeBld.CreateType();
Run = type.GetMethod("Target").CreateDelegate(typeof(TDelegate)) as TDelegate;
}
public TDelegate Run { get; }
}
}
자꾸 말하면, 동적으로 어셈블리 모듈 타입 메소드를 쭉 올리고 있다.
그때 받은 Expression을 바탕으로
Debugger.Break()
요약
한 번에 남미 아마존까지 날아가면 우선 디버깅할 수 있었다(`・ω・´)
도우미의 내용은 그 중 마음이 가면 다시 씁니다.
Reference
이 문제에 관하여(식 나무의 동적 생성 결과를 디버깅하기 위해 우리 취재반은 남미 아마존으로 날아갔다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/Tokeiya/items/5fd5cef5def7ff440f6d
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(식 나무의 동적 생성 결과를 디버깅하기 위해 우리 취재반은 남미 아마존으로 날아갔다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Tokeiya/items/5fd5cef5def7ff440f6d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)