我使用AppDomain动态加载程序集,实现热插拔功能,但是在Console程序中可以正常使用 跨域委托,在Asp.net中绑定事件时提示调用的目标发生异常。
加载程序集代码
using System;namespace AssemblyLoader
{
    //代理类
    public class Proxy : MarshalByRefObject
    {
        private System.Reflection.Assembly _assembly;        //加载程序集
        public void LoadAssembly(string assemblyFile)
        {
            this._assembly = System.Reflection.Assembly.LoadFrom(assemblyFile);
        }        //根据类名创建对象 
        public object GetObject(string FullClassName)
        {
            object obj = _assembly.CreateInstance(FullClassName, true, new System.Reflection.BindingFlags(), null, null, null, null);
            return obj;
        }        //根据类名和类型创建对象 
        public T GetInstance<T>(string FullClassName) where T : class
        {
            return GetObject(FullClassName) as T;
        }
    }
}
using System;namespace AssemblyLoader
{
    //加载程序集
    public class Loader
    {
        private AppDomain _appDomain;
        private Proxy _proxy;        //初始化代理
        public void InitProxy(string applicationName, string domainName, string currentAssemblyFile, string privateBinPath)
        {
            AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationName = applicationName;
            setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
            setup.PrivateBinPath = privateBinPath;
            setup.CachePath = setup.ApplicationBase;
            setup.ShadowCopyFiles = "true";
            setup.ShadowCopyDirectories = setup.ApplicationBase;
            setup.DisallowBindingRedirects = false;
            setup.DisallowCodeDownload = true;
            setup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            System.Security.Policy.Evidence adevidence = AppDomain.CurrentDomain.Evidence;
            this._appDomain = AppDomain.CreateDomain(domainName, adevidence, setup);
            var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
            string assemblyName = currentAssembly.GetName().FullName;
            this._proxy = (Proxy)this._appDomain.CreateInstanceFrom(currentAssembly.Location, typeof(Proxy).FullName).Unwrap();
        }        //加载程序集 调用代理
        public void LoadAssembly(string assemblyFile)
        {
            this._proxy.LoadAssembly(assemblyFile);
        }        //根据类名创建对象 调用代理
        public object GetObject(string FullClassName)
        {
            object obj = this._proxy.GetObject(FullClassName);
            return obj;
        }        //根据类名和类型创建对象 调用代理
        public T GetInstance<T>(string FullClassName) where T : class
        {
            return this._proxy.GetInstance<T>(FullClassName);
        }        //卸载程序域
        public void Unload()
        {
            try
            {
                if (this._appDomain != null)
                {
                    AppDomain.Unload(this._appDomain);
                    this._appDomain = null;
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
插件基类代码using System;namespace Compents
{
    //委托
    public class Delegates : MarshalByRefObject
    {
        public Func<object, object> GetObject;
    }
}using System;namespace Compents
{
    //接口
    public interface IPlugin
    {
        void Nomal();        object Run(object obj);
    }
}
插件代码
using System;
using Compents;namespace TestPlugin
{
    public class MyPlugin : Delegates, IPlugin
    {
        public void Nomal()
        {
            Console.WriteLine("Nomal");
        }        public object Run(object obj)
        {
            object objec = this.GetObject(obj);
            return objec;
        }
    }
}
在Console中运行正常
using System;
using AssemblyLoader;
using Compents;namespace ConsoleApp
{
    public class Program
    {
        static string dir = @"E:\LAB\TestPlugin\TestPlugin\bin\Debug";
        static string dll = @"E:\LAB\TestPlugin\TestPlugin\bin\Debug\TestPlugin.dll";        static void Main(string[] args)
        {
            try
            {
                Loader service = new Loader();
                string fullname = service.GetType().Assembly.FullName;
                service.InitProxy("TestApplication", "TestAppdomain", fullname, dir);
                service.LoadAssembly(dll);
                object obj = service.GetObject("TestPlugin.MyPlugin");                if (obj is IPlugin)
                {
                    IPlugin plugin = obj as IPlugin;
                    plugin.Nomal();
                }                if (obj is Delegates)
                {
                    Delegates del = obj as Delegates;
                    del.GetObject += MyClass.GetString;
                }                if (obj is IPlugin)
                {
                    IPlugin plugin = obj as IPlugin;
                    MyObject myobj = new MyObject();
                    myobj.something = "this is some line!";
                    object result = plugin.Run(myobj);
                    MyObject o = result as MyObject;
                    Console.WriteLine(o.something);
                }                Console.WriteLine("Run Complate");
                Console.Read();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.Read();
            }
        }
    }    public class MyClass
    {
        public static object GetString(object str)
        {
            return str;
        }
    }    public class MyObject : MarshalByRefObject
    {
        public string something { get; set; }
    }
}
同样的代码在Asp.net中就异常
using System;
using AssemblyLoader;
using Compents;namespace WebApplication1
{
    public partial class WebForm2 : System.Web.UI.Page
    {
        string dir = @"E:\LAB\TestPlugin\TestPlugin\bin\Debug";
        string dll = @"E:\LAB\TestPlugin\TestPlugin\bin\Debug\TestPlugin.dll";        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                Loader service = new Loader();
                string fullname = service.GetType().Assembly.FullName;
                service.InitProxy("TestApplication", "TestAppdomain", fullname, dir);
                service.LoadAssembly(dll);
                object obj = service.GetObject("TestPlugin.MyPlugin");                if (obj is IPlugin)
                {
                    IPlugin plugin = obj as IPlugin;
                    plugin.Nomal();
                }                if (obj is Delegates)
                {
                    Delegates del = obj as Delegates;
                    del.GetObject += MyClass.GetString;//这一句抛出异常 调用的目标发生了异常
                }                if (obj is IPlugin)
                {
                    IPlugin plugin = obj as IPlugin;
                    MyObject myobj = new MyObject();
                    myobj.something = "this is some line!";
                    object result = plugin.Run(myobj);
                    MyObject o = result as MyObject;
                    Console.WriteLine(o.something);
                }                Console.WriteLine("Run Complate");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }    public class MyClass
    {
        public static object GetString(object str)
        {
            return str;
        }
    }    public class MyObject : MarshalByRefObject
    {
        public string something { get; set; }
    }
}上述就是全部代码,在Asp.net中提示调用的目标发生了异常。我找了好久也没找到异常的原因,请各位大神帮我看看哪里有问题。
谢谢!

解决方案 »

  1.   

    运行时环境不一样,本地程序和网页程序不同的,在asp.net上 你没有完全加载他的依赖项
      

  2.   

    报的异常是找不到程序集WebApplication1, 但是这个程序集是调用插件程序集的发起者呀? 如果想让Asp.net和Console一样能跨域委托应该怎么做呢?
      

  3.   

    看异常时,这和跨域“委托”还是“调用”没关系。就是依赖的dll未加载。毕竟asp.net运行的iis下,其dll加载机制不同。
    你尝试把未加载的dll,通过代码加载试试。
      

  4.   

    还是不行,一样的异常。而且再次加载本程序集之前,我看了一下,当前域中已经有WebApplication1这个程序集了。