当前位置:编程学习 > C#/ASP.NET >>

C# 动态加载,卸载dll。

在webService中,需要动态的加载和卸载dll,请各路神仙帮忙看下问题所在。


    [WebMethod]
    public string ko()
    {
      AppDomain ad = AppDomain.CreateDomain("Classes");
            ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap(@"D:/messageDll/Classes.dll", "com.ms.AbcTest2"); // 这一步就提示错误System.Runtime.Serialization.SerializationException: 未解析成员
            obj.LoadAssembly();
            string strResult=obj.Invoke(@"D:/messageDll/Classes.dll", "HelloWorld").ToString();
            AppDomain.Unload(ad);
            return strResult;
    }


调用的dll如下

namespace com.ms
{
    [Serializable]
    public class AbcTest2 : ILogicalThreadAffinative 
    {
        public AbcTest2()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        public string HelloWorld()
        {
            return "Hello World ahhahahahahahah";
        }
    }
}


--------------------编程问答-------------------- ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap

这种的要求对象是可序列化的,在类上加 [Serializable] 特性 --------------------编程问答--------------------
引用 1 楼 fangxinggood 的回复:
ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap

这种的要求对象是可序列化的,在类上加 [Serializable] 特性


已经加了哦,看第二段代码 --------------------编程问答--------------------

ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap(@"D:/messageDll/Classes.dll", "com.ms.AbcTest2"); 
// 这一步就提示错误System.Runtime.Serialization.SerializationException: 未解析成员
--------------------编程问答-------------------- 另外个问题,为啥要用Domain,为了隔离吗?

直接用 Assembly.LoadFile / LoadFrom 
然后用 Activator.CreateInstance 不行么 --------------------编程问答--------------------
引用 4 楼 fangxinggood 的回复:
另外个问题,为啥要用Domain,为了隔离吗?

直接用 Assembly.LoadFile / LoadFrom 
然后用 Activator.CreateInstance 不行么


主要需要实现动态的卸载程序集,目的使得该服务升级不需要重启服务。但是没有Assembly.unload这样的方法,查阅了网上的一些解决方案,都是将其放到一个appdomin中的。然后条用appdomin.unload方法。 --------------------编程问答-------------------- public class AbcTest2 : ILogicalThreadAffinative 

加个继承

public class AbcTest2 : ILogicalThreadAffinative, MarshalByRefObject
--------------------编程问答-------------------- 重启服务有几毛钱损失呢?论证过吗? --------------------编程问答--------------------
var appDomain = AppDomain.CreateDomain("MyDomain");
var obj = appDomain.CreateInstanceFromAndUnwrap(@"MyTestLib.dll", "MyTestLib.Class1");
var result = obj.GetType().GetMethod("Foo").Invoke(obj, null);
Console.WriteLine(result);

//MyTestLib.dll
namespace MyTestLib
{
    public class Class1
    {
        public string Foo()
        {
            return "MyTestLib.Class1.Foo";
        }
    }
}


--------------------编程问答-------------------- 先序列化成object,看看成不成
Object obj = ad.CreateInstanceFromAndUnwrap(@"D:/messageDll/Classes.dll", "com.ms.AbcTest2"); --------------------编程问答--------------------
引用 8 楼 fangxinggood 的回复:
C# code
var appDomain = AppDomain.CreateDomain("MyDomain");
var obj = appDomain.CreateInstanceFromAndUnwrap(@"MyTestLib.dll", "MyTestLib.Class1");
var result = obj.GetType().GetMethod("Foo").Invoke(……



太感谢你们了,可我这还是不行,用的是vs2005,只好使用object了。 此时就提示需要序列化,修改了下

 [Serializable]
    public class AbcTest2 : MarshalByRefObject  //, ILogicalThreadAffinative
    ...

此时实例倒是创建成功了,不过它的类型为MarshalByRefObject  无法调用到它的方法,报空引用异常~~ --------------------编程问答-------------------- 面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~ --------------------编程问答--------------------
引用 11 楼 xuyiazl 的回复:
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~
面向接口编程~~~


哥们明示,小弟面向对象还没整明白了。。。 --------------------编程问答-------------------- loadlibrary
freelibrary --------------------编程问答--------------------
引用 13 楼 zanfeng 的回复:
loadlibrary
freelibrary


CSharp中貌似木有? --------------------编程问答-------------------- http://download.csdn.net/source/3485843

自己去下吧~ --------------------编程问答-------------------- help
    -load                       加载默认目录
    -loaddir    Directory       加载目录
    -loadfile   DllPath         加载插件文件
    -runall                     执行所有插件
    -run        PluginName      执行插件
    -unload     DllName         卸载插件
    -unloadall                  卸载所有插件

--------------------编程问答-------------------- u           p --------------------编程问答-------------------- help
    -load                       加载默认目录
    -loaddir    Directory       加载目录
    -loadfile   DllPath         加载插件文件
    -runall                     执行所有插件
    -run        PluginName      执行插件
    -unload     DllName         卸载插件
    -unloadall                  卸载所有插件
-load
     load : E:\PluginPlatform\bin\Debug\Plugins\PluginSample.dll
     load : E:\PluginPlatform\bin\Debug\Plugins\PluginSample1.dll
-runall
Hello Sample1
Hello Sample2
Hello Sample3
Hello Sample4
-unloadall
     unload PluginSample done ...
     unload PluginSample1 done ... --------------------编程问答--------------------
引用 15 楼 xuyiazl 的回复:
http://download.csdn.net/source/3485843

自己去下吧~


已下,非常感谢,不过是vs2010的,看不出效果,只好先看看代码了。 --------------------编程问答--------------------
引用 10 楼 yijianzuifen 的回复:
引用 8 楼 fangxinggood 的回复:

C# code
var appDomain = AppDomain.CreateDomain("MyDomain");
var obj = appDomain.CreateInstanceFromAndUnwrap(@"MyTestLib.dll", "MyTestLib.Class1");
var result = obj.GetT……


反射呀。
AppDomain appDomain = AppDomain.CreateDomain("MyDomain");
object obj = appDomain.CreateInstanceFromAndUnwrap(@"MyTestLib.dll", "MyTestLib.Class1");
object result = obj.GetType().GetMethod("Foo").Invoke(obj, null);
Console.WriteLine(result);

//MyTestLib.dll
namespace MyTestLib
{
    public class Class1
    {
        public string Foo()
        {
            return "MyTestLib.Class1.Foo";
        }
    }
}
--------------------编程问答--------------------
引用 10 楼 yijianzuifen 的回复:
引用 8 楼 fangxinggood 的回复:

C# code
var appDomain = AppDomain.CreateDomain("MyDomain");
var obj = appDomain.CreateInstanceFromAndUnwrap(@"MyTestLib.dll", "MyTestLib.Class1");
var result = obj.GetT……


另外,ls提到面向接口也是有道理的。你想强类型的使用加载之后的对象。
那么就需要定义一个接口,WebService需要引用接口所在的dll。
而动态加载实例所在的dll。然后上面可以强制转换成该接口并调用。

--------------------编程问答--------------------
引用 20 楼 fangxinggood 的回复:
AppDomain appDomain = AppDomain.CreateDomain("MyDomain");
object obj = appDomain.CreateInstanceFromAndUnwrap(@"MyTestLib.dll", "MyTestLib.Class1");
object result = obj.GetType().GetMethod("Foo").Invoke(obj, null);
Console.WriteLine(result);

//MyTestLib.dll
namespace MyTestLib
{
    public class Class1
    {
        public string Foo()
        {
            return "MyTestLib.Class1.Foo";
        }
    }
}



新建了个控制台程序,和你一样的代码,然后将编译好的dll放到debug文件夹下,运行,提示未标记可序列化错误,确定没有[Serializable]吗? --------------------编程问答-------------------- appDomain.CreateInstanceFromAndUnwrap

这个方法貌似对dll文件有要求,要是Assembly有unload就方便了 --------------------编程问答--------------------
using System.Reflection;

Assembly ass = Assembly.Load("testdll"); //加载dll文件
            Type tp = ass.GetType("testdll.MyClass"); //获取类名,必须 命名空间+类名
            Object obj = Activator.CreateInstance(tp,"男"); //建立实例
            PropertyInfo meth = tp.GetProperty("Six"); //获取方法
            Console.WriteLine(meth.GetValue(obj,null)); //Invoke调用方法


//.dll文件要放在bin\debug文件夹下
<C#入门经典4>812页
--------------------编程问答-------------------- 同样的问题 --------------------编程问答-------------------- --------------------编程问答-------------------- 我操,我TMD最近也遇到这个问题了。坐等求解 --------------------编程问答-------------------- 我也遇到这个问题了,求解答
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,