.NET: 如何通过AppDomain动态加载插件程序

这是今天课堂上的一个小例子程序

1. 接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Interfaces
{
    public interface IPlugin
    {
        void Run();
    }
}

2. 插件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PluginLib
{
    [Serializable]
    public class Plugin:Interfaces.IPlugin
    {
        public void Run() {
            Console.WriteLine("插件在运行");
        }


    }
}

3. 主程序

            AppDomain plugindomain = AppDomain.CreateDomain("PluginDomain");
            #region 使用接口的方式来动态执行方法
            Interfaces.IPlugin plugin = (Interfaces.IPlugin)plugindomain.CreateInstanceFromAndUnwrap("PluginLib.dll", "PluginLib.Plugin");

            plugin.Run();


            Console.WriteLine("在插件程序域中加载的程序集");
            foreach (var item in plugindomain.GetAssemblies())
            {
                Console.WriteLine(item.FullName);
            }
            #endregion

结果如下

image

注意:这种方式加载的插件,里面的类型必须声明可序列化([Serializable] ),否则就会出现下面的错误

image

但是,如果插件真的没有声明可序列化,是不是就没有办法呢?也不是这么说

4. 在主程序中添加一个TypeLoader

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Reflection;
using System.IO;

namespace _08_AppDomain_ServiceSample
{
    [Serializable]
    public class TypeLoader
    {
        public Assembly LoadAssembly(string path) {
            return Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, path));
        }
    }
}

5. 修改代码,利用TypeLoader作为中间人,去动态加载那些插件程序集

            #region 使用加载代理的方式
            TypeLoader loader = (TypeLoader)plugindomain.CreateInstanceFromAndUnwrap("08_AppDomain_ServiceSample.exe", typeof(TypeLoader).FullName);
            Interfaces.IPlugin plugin = (Interfaces.IPlugin)loader.LoadAssembly("PluginLib.dll").CreateInstance("PluginLib.Plugin");
            plugin.Run();
            Console.WriteLine("在插件程序域中加载的程序集");
            foreach (var item in plugindomain.GetAssemblies())
            {
                Console.WriteLine(item.FullName);
            }

            AppDomain.Unload(plugindomain);

            #endregion

image

原文地址:https://www.cnblogs.com/chenxizhang/p/1625953.html