简而言之:如何在生成程序上调试调试会话期间生成的代码?(见下面的代码)
我面临以下问题:我想从生成它的应用程序调试动态生成/编译的代码.我提供了一个简单的例子来澄清它.这个例子不需要调试!我真正的应用程序生成更多的行和代码,真正证明调试,相信我:-)我想知道是否有一种方法来调试或放置断点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 …Run Code Online (Sandbox Code Playgroud) 这是我目前的情况 - 我有一个应用程序使用CodeDom编译作为字符串的C#代码.我有一个存储密码的SecureString,我想知道是否有任何方法可以将SecureString变量作为SecureString传递给已编译的代码?
这是一些示例代码:
SecureString securePassword = getSecurePass();
string codeString =
@"using System;
using System.Security;
namespace SomeProgram
{
class MyClass
{
static void Main(string[] args)
{
SecureString securePass = new SecureString();
// somehow set this equal to the securePassword variable
}
}
}";
// Compiler Code
CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");
string outFile = "output.exe";
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = true;
parameters.OutputAssembly = outFile;
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, codeString);
Run Code Online (Sandbox Code Playgroud)
我找不到办法做到这一点,我想这实际上是不可能的,而我可能只是将密码存储在加密文件中并从中读取?
有没有办法用CodeDom生成类约束.
因为当我使用类似的东西
var method = new CodeMemberMethod();
var genericParam = new CodeTypeParameter("InterfaceType");
genericParam.Constraints.Add("class");
method.TypeParameters.Add(genericParam);
Run Code Online (Sandbox Code Playgroud)
生成的代码就像
private InterfaceType GetImpl<InterfaceType>()
where InterfaceType : @class
{
}
Run Code Online (Sandbox Code Playgroud)
我发现最好的解决方法是在课前使用前导空格
genericParam.Constraints.Add(" class");
Run Code Online (Sandbox Code Playgroud)
但这似乎充其量只是一种解决方法.
尝试使用ComponentSerializationService反序列化时,会填充未找到引用的错误:
public ICollection Deserialize(object serializationData)
{
var serializationStore = serializationData as SerializationStore;
var componentSerializationService = _serviceProvider.GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;
var collection = componentSerializationService.Deserialize(serializationStore);
}
Run Code Online (Sandbox Code Playgroud)
错误如:
找不到类型'System.Drawing.Size'.请确保引用包含此类型的程序集.如果此类型是开发项目的一部分,请确保使用当前平台或任何CPU的设置成功构建项目.
在这里,我通过了Button控件并设置了size属性.
我有一个我正在研究的C#应用程序远程加载它的代码,然后运行它(为了争论,你可以假设应用程序是安全的).
代码是C#,但它作为XML文档发送,解析为字符串,然后编译和执行.
现在,我想要做的事情 - 并且比我预期的要困难得多 - 能够解析整个文档,并且在编译之前,在每行执行之后插入其他命令.
例如,考虑代码:
using System;
using System.Collections.Generic;
using System.Linq;
namespace MyCode
{
static class MyProg
{
static void Run()
{
int i = 0;
i++;
Log(i);
}
}
}
Run Code Online (Sandbox Code Playgroud)
解析后我想要的更像是:
using System;
using System.Collections.Generic;
using System.Linq;
namespace MyCode
{
static class MyProg
{
static void Run()
{
int i = 0;
MyAdditionalMethod();
i++;
MyAdditionalMethod();
Log(i);
MyAdditionalMethod();
}
}
}
Run Code Online (Sandbox Code Playgroud)
请记住明显的陷阱 - 我不能在每次分号后都有它,因为这在getter/setter中不起作用,即:
转换:
public string MyString { get; set; }
Run Code Online (Sandbox Code Playgroud)
至:
public string MyString { …Run Code Online (Sandbox Code Playgroud) 我正在寻找与语言无关(至少在某些范围内)源代码生成的System.CodeDom命名空间,并且我发现了一些阻止使用的信息CodeDom.
我认为这篇早期博客文章中描述的一些遗漏现在已经修复,而且CodeDom似乎没有提供创建switch语句的方法的事实仍然允许 - 性能较差? - 没有弄乱生成类型的公共接口的变通方法.这同样适用于自动C#属性和集合初始值设定项.
但是,其他遗漏实际上无法解决,例如无法创建终结器,无法声明扩展方法,或者缺乏对通用引用类型约束的直接支持.
请注意,CodeSnippetTypeMember通过任何其他方式使用或注入文字源代码片段的建议解决方案并不令人满意,因为它们不是与语言无关的 - 从而消除了整个使用点CodeDom而不是String.Format文字代码片段.
最后,甚至在这个SO问题中建议"CodeDom是失败的,表达树(或者更确切地说是"语句"树)是前进的方式" - 尽管没有任何解释如何从表达式树中实际获取任何源代码(除了不能用表达式树声明类的限制之外.
CodeDom仍然是生成源代码的首选方法,还是当前的BCL提供了一个我想不到的名称的任何模糊替换?
我有一些C#代码(让我们称之为"脚本")我在运行时编译.它使用我的主程序中的接口来访问其功能.编译完成后我就CompilerResults.CompiledAssembly可以了CreateInstance(Type).
一旦我完成了使用脚本,我想完全卸载.据我所知,如果我创建一个单独的应用程序域,我只能这样做:将 DLL加载到单独的AppDomain中
我有一些与我的实施有关的问题:
ReferencedAssemblies.Add(typeof(Interface).Assembly.Location)在编译之前正在做的事情.CompilerParameters GenerateInMemory=true,还是必须将其保存在某个地方?我想要做的是读取C#代码,解析它,插入一些方法调用并最终编译它.
是否可以将C#源代码(字符串列表)转换为CodeDOM对象?
我想使用创建枚举CodeDom API.我在互联网上搜索得足够多,而且我得到的结果几乎没用.
我想要产生的是
public enum bug_tracker_type
{
[Description("Bugzilla")]
Bugzilla,
[Description("Debbugs")]
Debbugs,
[Description("PHP Project Bugtracker")]
PHP_Project_Bugtracker,
[Description("Google Code")]
Google_Code
}
Run Code Online (Sandbox Code Playgroud)
我使用CodeTypeDeclaration并将其IsEnum属性设置为true,创建了一个名称,并设置了它的属性.
现在最大的问题是如何填充身体?
我试过了
CodeTypeMember mem = new CodeTypeMember();
mem.Name = WadlSharpUtils.CreateIdentifier(discreteValue.value);
mem.CustomAttributes.Add(new CodeAttributeDeclaration(discreteValue.value));
// enumCandidate is an instance of CodeTypeDeclaration
enumCandidate.Members.Add(mem);
Run Code Online (Sandbox Code Playgroud)
虽然使用这个解决方案我可以生成描述属性,但行结束;与否,
我需要使用编译一些代码CodeDomProvider.CompileAssemblyFromSource.如何进行调试呢?基本上,我想编译它,创建一个类型的实例,然后进入该类型的代码.
codedom ×10
c# ×9
.net ×5
appdomain ×1
assemblies ×1
debugging ×1
generics ×1
parsing ×1
reflection ×1