请教几个动态编译和动态加载的细节概念问题。有经验的来给看看。

fengyecsdn 2009-02-20 10:48:24
小弟有个win项目。
一个主体框架,程序目录下有asm目录 第三方可以写一些插件子类。放在此目录下或者之下的子目录中。可以是 CS代码VB代码文件 也可以是DLL文件。 用户在使用中选择项目 加载 执行。

关于动态加载我有些细节问题。
1:针对DLL加载没问题,但是我希望能卸载,换项目的时候可以卸载之前的dll。孟子给了个例子,是用APPDOMAIN的方法,卸载APPDOMAIN也就卸载了DLL。新建APPDOMAIN以后在这个AD里加载一个代理类来作为主体程序集。
不过这里有问题是要求AD里的代理类型必须继承MarshalByRefObject。才可以被原本的DOMAIN操作。但是这个代理类中的内部属性类型都是我的WIN项目框架中的类型,这些类型还需要继承MarshalByRefObject么?
还有,动态加载的类里要传进去一个我框架的对象,以便实现互操作。我这个对象需要继承MarshalByRefObject么? 这些除代理类外的类型对象可以实现穿透DOMIAN的操作么?
当新AD构建以后也构造了插件类,并传递进去一个框架的成员对象,插件类注册了这个对象的某些事件。当DOMAIN卸载以后,这些事件会出错么?
如果不采用APPDOMAIN,直接在本域内加载程序集,还有其他卸载办法么?因为用户可能会更换多个插件,而这些插件都要使用框架的很多资源,为避免冲突,需要隔离它们。就算是不卸载,也要让用过的程序集彻底和当前框架断绝关系。这些插件不是我们作的,是允许任何人写的,很难保证这些作者会不会清理干净自己的痕迹,并且不伤害到框架本身呢。。。

2关于动态编译问题。我看到动态编译的时候要置顶原文件,并加入引用程序集。但是这个问题我不好控制的吧,首先肯定要引用.NET的几个基本程序集(system.dll system.xml.dll system.windows.forms.dll ....)
还有我的程序集 MyEngince.dll 这个MyEngince.dll已经在执行中的框架里了,还需要添加这个么?(采用新APPDOMAIN和采用当前APPDOMAIN是否一样?)还有第三方写插件的时候没准还要引用什么DLL,如何知道并且处理啊? 能不能不添加引用程序集 直接从内存和系统里获取需要的程序集?

这些问题都没找到帮助文档。请各位大侠帮忙了。
...全文
280 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
天乐 2009-02-26
  • 打赏
  • 举报
回复
我做过类似的东西,为WPF表单编辑器提供运行时支持。

采取的AppDomain的方式动态编译、加载、卸载表单。

WPF的对象跨域传递更麻烦,微软已承认其提供的穿透方式有bug,所以不能作为正规项目使用。

先大概说说思路,详细的有点忘了,回头看看代码再说。

1、程序集已加载就卸不掉,要想卸载,必须放到AppDomain里面,目前我不知道还有别的方法,微软官方文档也推荐这么做,有个人似乎还针对为何要这样做给出了解释

2、在我们项目中,在需要动态编译的源码文件头中,以注释+特殊标记的方式添加该源码引用的其他dll或其他源码文件,编译时解析,做出相应处理

3、跨域的对象通信,在C#中,必须继承MarshalByRefObject,但应该也有其他特殊的变通手段,没详细研究过,初步思路是通过共享内存来做中间交互

4、插件不能妥善处理自己的资源,是它的问题,是作者的问题,与你无关,插件的作者应该自行保障,就像c++中的动态内存一样,谁申请的谁释放,别人管不着

5、主框架里的程序集如果插件要用,必须也要加载到其AppDomain中去,可以把AppDomain理解为近似为一个独立的进程,独立于主进程

6、动态编译也可以实现UI,我们的项目中,动态编译后需要呈现一个WPF的Window界面的

你先看看,有不明白再详细讨论一下
zt_100094 2009-02-24
  • 打赏
  • 举报
回复
//主程序的接口
namespace TestApplication
{
public interface ICom
{
void Show();
}
}

//DLL的类对象
namespace Demo
{
public class Common : ICom
{
void ICom.Show()
{
Console.WriteLine("动态加载DLL中的类");
}
}
}
//测试类。。
namespace TestApplication
{

class Program
{
static void Main(string[] args)
{
ICom com = Assembly.LoadFile(@"F:\project\TestApplication\TestApplication\bin\Debug\Demo.dll").CreateInstance("Demo.Common") as ICom;
com.Show();//输出结果:动态加载DLL中的类
Console.Read();
}
}
}

fenglaijun 2009-02-24
  • 打赏
  • 举报
回复
楼上的在干嘛呀?
fengyecsdn 2009-02-23
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 fenglaijun 的回复:]
也许答非所问。。不过谢谢楼主。。我学会了怎么不添加引用就加载DLL来调用其中类地方法谢谢。
[/Quote]


哈哈 。。。
fenglaijun 2009-02-23
  • 打赏
  • 举报
回复
也许答非所问。。不过谢谢楼主。。我学会了怎么不添加引用就加载DLL来调用其中类地方法谢谢。
fenglaijun 2009-02-23
  • 打赏
  • 举报
回复

//主程序的接口
namespace TestApplication
{
public interface ICom
{
void Show();
}
}

//DLL的类对象
namespace Demo
{
public class Common : ICom
{
void ICom.Show()
{
Console.WriteLine("动态加载DLL中的类");
}
}
}
//测试类。。
namespace TestApplication
{

class Program
{
static void Main(string[] args)
{
ICom com = Assembly.LoadFile(@"F:\project\TestApplication\TestApplication\bin\Debug\Demo.dll").CreateInstance("Demo.Common") as ICom;
com.Show();//输出结果:动态加载DLL中的类
Console.Read();
}
}
}


fenglaijun 2009-02-23
  • 打赏
  • 举报
回复

namespace Demo
{
public class Common
{
public void Show()
{
Console.WriteLine("动态加载DLL中的类");
}
}
}

namespace Demo
{
class Program
{
static void Main(string[] args)
{
ICom com = Assembly.LoadFile(@"F:\project\TestApplication\TestApplication\bin\Debug\Demo.dll").CreateInstance("Demo.Common") as ICom;
com.Show();//输出结果:动态加载DLL中的类
Console.Read(); }
}
}
fenglaijun 2009-02-23
  • 打赏
  • 举报
回复

namespace Demo
{
public class Common
{
public void Show()
{
Console.WriteLine("动态加载DLL中的类");
}
}
}

namespace Demo
{
class Program
{
static void Main(string[] args)
{
ObjectHandle handle = System.Activator.CreateInstance("Demo", "Demo.Common");
Common co = handle.Unwrap() as Common;
co.Show();//输出结果:动态加载DLL中的类
Console.Read();
}
}
}
fenglaijun 2009-02-23
  • 打赏
  • 举报
回复

namespace Demo
{
public class Common
{
public void Show()
{
Console.WriteLine("动态加载DLL中的类");
}
}
}

namespace Demo
{
class Program
{
static void Main(string[] args)
{
ObjectHandle handle = System.Activator.CreateInstance("Demo", "Demo.Common");
Console.WriteLine(handle.Unwrap().ToString());//输出结果Demo.Common
Console.Read();
}
}
}
fenglaijun 2009-02-23
  • 打赏
  • 举报
回复
//动态加载类,有12个重载方法。。自己看看
System.Activator.CreateInstance()+12;
大神来了丶 2009-02-23
  • 打赏
  • 举报
回复
顶一下
BlueskyWide 2009-02-23
  • 打赏
  • 举报
回复
请.net高手来解。
abcyzq 2009-02-23
  • 打赏
  • 举报
回复
学习来了。
fuyuxin19801120 2009-02-23
  • 打赏
  • 举报
回复
mark
soaringbird 2009-02-23
  • 打赏
  • 举报
回复
http://blog.csdn.net/soaringbird/archive/2008/04/14/2291531.aspx
看看这个有没有帮助
fengyecsdn 2009-02-21
  • 打赏
  • 举报
回复
回楼上 目前还真的不用在插件里涉及界面的东西。。插件只是为主程序的数据进行操作,和一些事件处理。并不直接操作界面的东西。。但是有可能会涉及其他方面,比如通信,数据库之类的
haroun 2009-02-21
  • 打赏
  • 举报
回复
一般来说,如果程序集是放在同一个目录下,创建程序域,关联的程序集会被自动加载.我做过一个组件管理器,证实的结果就是这样的.虽然我还是加入了事件:AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);来达到加载依赖的目的,但是经调试,没有执行过该事件的委托方法.

另外,我以前做过一个插件管理器,本来也想用创建AD的形式,但是发现这样的插件不能有界面,结果只能放弃.于是把所有程序集都加载到主域里,虽然表面是加载插件的形式,但是不能动态卸载以实现管理.你现在做的插件是没有UI界面的吗?
hubofly 2009-02-21
  • 打赏
  • 举报
回复
顶一下

今天不开心,喝酒了,问题也看不了了
yanlongwuhui 2009-02-21
  • 打赏
  • 举报
回复
关注
feifeiyiwen 2009-02-21
  • 打赏
  • 举报
回复
学习帮顶
加载更多回复(4)

110,532

社区成员

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

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

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