jde*_*aan 14 .net c# debugging code-generation codedom
简而言之:如何在生成程序上调试调试会话期间生成的代码?(见下面的代码)
我面临以下问题:我想从生成它的应用程序调试动态生成/编译的代码.我提供了一个简单的例子来澄清它.这个例子不需要调试!我真正的应用程序生成更多的行和代码,真正证明调试,相信我:-)我想知道是否有一种方法来调试或放置断点HelloWorld
.单步调用InvokeMethod调用不起作用.也许解决方案涉及在调用站点对生成的程序集进行代码修改.
我已经看了很多问题(例如在Visual Studio .NET中调试动态加载的程序集),但没有一个有助于解决问题(如果可以解决的话?)
我从http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=118中获取代码作为基础并修复了已废弃的调用.除此之外,我在内存中即时生成了程序集,并且调用运行良好.我明确生成了一个包含Debug信息的程序集,这给了我希望:为什么在没有调试的情况下会有选项呢?
using System;
using System.Text;
using System.IO;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
namespace DynamicAssembly
{
class CreateCompileExecute
{
[STAThread]
static void Main(string[] args)
{
// Creates a text file to store the new class
StringBuilder builder = new StringBuilder();
builder.AppendLine("using System;");
builder.AppendLine("namespace CSharpFriendsRocks");
builder.AppendLine("{");
builder.AppendLine("class CSharpFriends");
builder.AppendLine("{");
builder.AppendLine("public CSharpFriends() {" +
" Console.WriteLine(\"The CSharpFriends type is constructed\"); }");
builder.AppendLine("public void HelloWorld() {" +
" Console.WriteLine(\"Hello World - CSharpFriends.Com Rocks.\"); }");
builder.AppendLine("}");
builder.AppendLine("}");
// Create the C# compiler
CSharpCodeProvider csCompiler = new CSharpCodeProvider();
// input params for the compiler
CompilerParameters compilerParams = new CompilerParameters();
compilerParams.OutputAssembly = "CSharpFriends.dll";
compilerParams.GenerateInMemory = true;
compilerParams.IncludeDebugInformation = true;
compilerParams.ReferencedAssemblies.Add("system.dll");
compilerParams.GenerateExecutable = false; // generate the DLL
// Run the compiler and build the assembly
CompilerResults results = csCompiler.CompileAssemblyFromSource(
compilerParams, builder.ToString());
// Load the generated assembly into the ApplicationDomain
Assembly asm = results.CompiledAssembly;
Type t = asm.GetType("CSharpFriendsRocks.CSharpFriends");
// BindingFlags enumeration specifies flags that control binding and
// the way in which the search for members and types is conducted by reflection.
// The following specifies the Access Control of the bound type
BindingFlags bflags = BindingFlags.DeclaredOnly | BindingFlags.Public
| BindingFlags.NonPublic | BindingFlags.Instance;
// Construct an instance of the type and invoke the member method
Object obj = t.InvokeMember("HelloWorld", bflags |
BindingFlags.CreateInstance, null, null, null);
// Call the method
t.InvokeMember("HelloWorld", bflags | BindingFlags.InvokeMethod,
null, obj, null);
}
}
}
Run Code Online (Sandbox Code Playgroud)
jde*_*aan 13
我终于找到了一种方法来解决它后发现我的问题是如何调试/中断编码编译代码的重复,这对我来说并不明显.bbmud在那里提供了一个非常好的提示,以使调试器正常工作,但不告诉如何进入代码.我添加了一个对包含我想在脚本中实现的接口的程序集的引用:
compilerParams.ReferencedAssemblies.Add(typeof(IPlugin).Assembly.Location);
compilerParams.GenerateExecutable = false; // generate the DLL
// if you want to debug, this is needed...
compilerParams.GenerateInMemory = false;
compilerParams.TempFiles = new TempFileCollection(Environment.
GetEnvironmentVariable("TEMP"), true);
Run Code Online (Sandbox Code Playgroud)
现在,当我考虑CSharpFriends
成为一个实现时IPlugin
,我可以通过强制转换obj
上面的内容来获取接口:
IPlugin script = obj as IPlugin;
Run Code Online (Sandbox Code Playgroud)
然后调试接口方法或属性就像平常一样容易!添加的诀窍
System.Diagnostics.Debugger.Break();
Run Code Online (Sandbox Code Playgroud)
在脚本代码中也运行良好,但需要更改脚本.由于应用程序内部的代码总是需要根据某种机制(对属性或接口的反思)知道脚本中有哪种方法,因此使用两者都知道的接口对我来说是一个非常可接受的解决方案.
我希望它可以帮助别人.