15

要するに、生成プログラムのデバッグ セッション中に生成されたコードをどのようにデバッグできますか? (以下のコードを参照)

次の問題に直面しています: 動的に生成/コンパイルされたコードを、それを生成するアプリケーションからデバッグしたいと考えています。それを明確にするために、過度に単純化された例を提供しました。この例はデバッグを必要としません! 私の実際のアプリは、デバッグを本当に正当化するより多くの行とコードを生成します。私を信じてください:-) デバッグする方法または にブレークポイントを配置する方法があるかどうか知りたいですHelloWorld。InvokeMethod 呼び出しにステップインしても機能しません。おそらく解決策には、生成されたアセンブリへの呼び出しサイトでのコード変更が含まれます。

私はすでに多くの質問を見てきました (たとえば、Visual Studio .NET で動的に読み込まれたアセンブリをデバッグする) が、問題の解決に役立つものはありませんでした (解決できる場合)。

http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=118からコードをベースとして取得し、廃止された呼び出しを修正しました。これに加えて、メモリ内でオンザフライでアセンブリを生成しましたが、呼び出しはうまく機能しています。デバッグ情報を含むアセンブリを明示的に生成しましたが、希望が持てます: デバッグが不可能な場合、なぜオプションがあるのでしょうか?

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);
        }
    }
}
4

2 に答える 2

14

私の質問がコードダムコンパイル済みコードでデバッグ/ブレークする方法の複製であることがわかった後、最終的に回避する方法を見つけましたが、これは私にはわかりませんでした。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);

CSharpFriendsの実装であると考えると、上記IPluginをキャストすることでインターフェイスを取得できます。obj

IPlugin script = obj as IPlugin;

インターフェイス メソッドまたはプロパティへの呼び出しのデバッグは、通常どおり簡単です。追加のコツ

 System.Diagnostics.Debugger.Break();

スクリプト コード内も問題なく動作しますが、スクリプトを変更する必要があります。アプリケーション内のコードは、なんらかのメカニズム (属性またはインターフェイスのリフレクション) に従って、スクリプト内にあるメソッドの種類を常に知る必要があるため、両方で認識されるインターフェイスを使用することは、私にとって非常に受け入れられる解決策です。

それが他の誰かに役立つことを願っています。

于 2009-10-20T14:14:55.660 に答える
0

Visual Studio 2010 は、デバッガーでこれを穏やかに処理します。アップグレードしてから驚いた。お役に立てば幸いです。

于 2010-05-14T09:36:53.777 に答える