<问题的延续> 关于[动态代码]编译后如何实现调用主应用程序里原来的方法!请大家关注...

shinaterry 2007-05-08 11:27:21
上一个问题已经解决,地址:http://community.csdn.net/Expert/topic/5516/5516889.xml?temp=.9189264

如题!问题的缘由 请参阅如上地址...

我现在已经通过CodeDom动态的把字符串编译成程序集,并保存在内存当中(可调用)!

现在我想实现的是,在动态生成的[程序集]里面调用主应用程序的方法(注意:这是已编译好的物理文件)...

不知能否实现,请有相关经验的朋友 / 上一贴回答的朋友继续指教...

先谢了...

^o^
...全文
295 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
王集鹄 2007-05-09
  • 打赏
  • 举报
回复
//也不知道这个是不是你想要的,或者是最简单的
//就是实现动态编译的程序回调静态的方法
//抛砖引玉吧

private void MyDelegate(object sender, EventArgs e)
{
MessageBox.Show("Zswang 路过");
}

private void button1_Click(object sender, EventArgs e)
{
ICodeCompiler vCodeCompiler = new CSharpCodeProvider().CreateCompiler();
CompilerParameters vCompilerParameters = new CompilerParameters();
vCompilerParameters.GenerateExecutable = false;
vCompilerParameters.GenerateInMemory = true;

string vSource =
"using System;\n" +
"public class Temp\n" +
"{\n" +
" public EventHandler myDelegate;\n" +
" public void Test()\n" +
" {\n" +
" if (myDelegate != null)\n" +
" myDelegate.Invoke(null, null);\n" +
" }\n" +
"}\n";
CompilerResults vCompilerResults =
vCodeCompiler.CompileAssemblyFromSource(vCompilerParameters, vSource);

Assembly vAssembly = vCompilerResults.CompiledAssembly;
object vTemp = vAssembly.CreateInstance("Temp");
FieldInfo vMyDelegate = vTemp.GetType().GetField("myDelegate");
vMyDelegate.SetValue(vTemp, new EventHandler(MyDelegate));
MethodInfo vTest = vTemp.GetType().GetMethod("Test");
vTest.Invoke(vTemp, null);
}
王集鹄 2007-05-09
  • 打赏
  • 举报
回复
//找到一个更好的解决方案,如果楼主还能看到的话

private void button1_Click(object sender, EventArgs e)
{
ICodeCompiler vCodeCompiler = new CSharpCodeProvider().CreateCompiler();
CompilerParameters vCompilerParameters = new CompilerParameters();
vCompilerParameters.GenerateExecutable = false;
vCompilerParameters.GenerateInMemory = true;

vCompilerParameters.ReferencedAssemblies.Add(GetType().Module.FullyQualifiedName);
vCompilerParameters.ReferencedAssemblies.Add("System.dll");
vCompilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");

string vSource =
"using " + GetType().Namespace + ";\n" +
"using System.ComponentModel;\n" +
"using System.Windows.Forms;\n" +
"public class Temp\n" +
"{\n" +
" public void Test()\n" +
" {\n" +
" new Form1().Show();" +
" }\n" +
"}\n";
Console.WriteLine(typeof(Component).Module.FullyQualifiedName);
CompilerResults vCompilerResults =
vCodeCompiler.CompileAssemblyFromSource(vCompilerParameters, vSource);
if (vCompilerResults.Errors.Count > 0)
{

foreach (CompilerError vCompilerError in vCompilerResults.Errors)
{
Console.WriteLine("错误:" + vCompilerError.ErrorText);
}
return;
}

Assembly vAssembly = vCompilerResults.CompiledAssembly;
object vTemp = vAssembly.CreateInstance("Temp");
MethodInfo vTest = vTemp.GetType().GetMethod("Test");
vTest.Invoke(vTemp, null);
}
shinaterry 2007-05-09
  • 打赏
  • 举报
回复
好吧!

虽然是麻烦点!但也只好结贴了...

谢谢...^o^
王集鹄 2007-05-09
  • 打赏
  • 举报
回复
//当然变通一下,把一条语句动态的组合在代码中

"public class Temp\n" +
"{\n" +
" public EventHandler myDelegate;\n" +
" public void Test()\n" +
" {\n" +
这里加入一条语句 +
" }\n" +
"}\n";
王集鹄 2007-05-09
  • 打赏
  • 举报
回复
据我所知:C#是以类为单位,这样单独的语句没有办法编译,语法已经限制了
shinaterry 2007-05-09
  • 打赏
  • 举报
回复
嗯! 可以啦!

非常感谢zswang! 可是这种方法实现起来有点麻烦...

请问能不能直接在[应用程序]里编译代码,而不用另外在内存里生成程序集->反射调用呢?

比如说:

string vSource = "MessageBox.Show(Application.StartPath);";

就只编译这行代码弹出一个对话框!

( 嗯!就相当于在已经编绎好的程序集里动态追加一行或多行代码 )
shinaterry 2007-05-09
  • 打赏
  • 举报
回复
如果要实现我所说的功能...

是不是也应该在[动态代码]里面用上反射技术呢???
王集鹄 2007-05-09
  • 打赏
  • 举报
回复
如果要实例化一个类
你可把类传递进去

Type vType = GetType(); // 得到类 // or typeof(TForm1)


object vObject = Activator.CreateInstance(vType); // 创建实例
shinaterry 2007-05-09
  • 打赏
  • 举报
回复
TO:zswang

谢谢!

我的意思是:

能在[动态代码]:string vSource =
"using System;\n" +
"public class Temp\n" +
"{\n" +
" public EventHandler myDelegate;\n" +
" public void Test()\n" +
" {\n" +
" if (myDelegate != null)\n" +
" myDelegate.Invoke(null, null);\n" +
" }\n" +
"}\n";里面实例化[主应用程序集]的类 或者 直接调其类的静态方法...


用委托与事件,的确是可以回调(实现),可是也不可以实例化我原来的类...
shinaterry 2007-05-09
  • 打赏
  • 举报
回复
哦! 原来这样的...

现在终于可以松口气了...

高手出马就是不同...^o^

谢谢!

你的QQ是多少?想跟您交个朋友..
王集鹄 2007-05-09
  • 打赏
  • 举报
回复
项目属性->调试->启动调试器
取消启用Visual Studio宿主进程
shinaterry 2007-05-09
  • 打赏
  • 举报
回复
我尝试过将[动态编译]的那部分功能单独封装成DLL再引用,可是还是避免不了...

系统还是会新开一个应用程序的进程(这样会占用双倍系统资源)
shinaterry 2007-05-09
  • 打赏
  • 举报
回复
TO:zswang

哈哈!幸好我有个习惯,会经常翻阅旧资料和查看自己的贴子...

不然就错过了...^o^

对于您的热心,我真的不知道怎样道谢才好...

你最后的那段代码我也用上了,可是我又发现了一个问题...

在[动态代码]里引用[主应用程序]并导入其命名空间.操作系统会再次开一个新进程...

(任务管理器会看到两个相同的进程)

在我关闭应用程序窗口后,另次的一个新进程还会在继续运行(没有释放)...

不知道你有没有察觉呢?

因为这次任务要求必须在主程序里动态编译...

这样子的话,我每次关闭程序都要foreach来中止另外的新进程,再说这样的运行效率会偏低...

不知道如何才能避免?
王集鹄 2007-05-08
  • 打赏
  • 举报
回复
类似回调?我想可以通过delegate实现
shinaterry 2007-05-08
  • 打赏
  • 举报
回复
UP

非常着急...

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧