码迷,mamicode.com
首页 > 其他好文 > 详细

程序集与应用程序域基础练习

时间:2016-08-17 18:01:55      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:

1. 程序集

程序集是自我描述的安装单位。

程序集清单:描述了程序集和引用它所需要的所有信息。

查看程序集:ildasm 工具

程序集特性:VS会生成 AssemblyInfo.cs 文件,描述程序集特性,用于配置程序集清单。

 

用“C#”高级编程的例子来学习创建与动态加载程序集:

   public class CodeDriver
    {
        private string prefix =
            "using System;" +
            "public static class Driver" +
            "{" +
            "public static void run()" +
            "{";

        private string postfix =
            "}" +
            "}";

        public string CompileAndRun(string input, out bool hasError)
        {
            hasError = false;
            string returnData = null;

            CompilerResults results = null;
            using(var provider = new CSharpCodeProvider())
            {
                var options = new CompilerParameters();
                options.GenerateInMemory = true;

                var sb = new StringBuilder();
                sb.Append(prefix);
                sb.Append(input);
                sb.Append(postfix);

                results = provider.CompileAssemblyFromSource(options, sb.ToString());
            }

            if(results.Errors.HasErrors)
            {
                hasError = true;
                var errMessage = new StringBuilder();
                foreach(CompilerError error in results.Errors)
                {
                    errMessage.AppendFormat("{0} {1}", error.Line, error.ErrorText);
                }
                returnData = errMessage.ToString();
            }
            else
            {
                TextWriter temp = Console.Out;
                var writer = new StringWriter();
                Console.SetOut(writer);
                Type driverType = results.CompiledAssembly.GetType("Driver");   //通过反射在动态编译后的程序集中找到 Driver 这个静态类型

                driverType.InvokeMember("Run", BindingFlags.InvokeMethod | BindingFlags.Static
                    | BindingFlags.Public, null, null, null);                   //通过反射调用 Driver 的静态方法 Run
                returnData = writer.ToString();
            }

            return returnData;
        }
    }

  值得注意的是:只要实例化了一种类型的程序集,或者使用了该类型的一个方法,就会自动加载所引用程序集。

  另外,每次加载程序集,都会消耗越老越多的内存。如果要卸载程序集,就需要使用应用程序域。

  

2. 应用程序域

  应用程序域-可以确保在同一进程中不能访问另外一个应用程序的内存;多个应用程序可以运行在一个进程的多个应用程序域中。

  AppDomain 类用于创建与终止应用程序域,加载和卸载程序集。

示例:

程序集A:

    public class Demo
    {
        public Demo(int val1, int val2)
        {
            Console.WriteLine("Constructor with the value {0}, {1} in domain" +
                "{2} called", val1, val2, AppDomain.CurrentDomain.FriendlyName);
        }
    }

    public class Program
    {
        static void Main()
        {
            Console.WriteLine("Main in domain {0} called", AppDomain.CurrentDomain.FriendlyName);
            Console.ReadLine();
        }      
    }

程序集B:

    class AProgram
    {
        static void Main(string[] args)
        {
            AppDomain currentDomain = AppDomain.CurrentDomain;
            Console.WriteLine(currentDomain.FriendlyName);
            AppDomain secondDomain = AppDomain.CreateDomain("New Domain");
            secondDomain.ExecuteAssembly("Delegate_Test.exe");
        }
    }

启动程序集B--输出结果:

技术分享

使用 ExecuteAssembly 应该是执行另外一个程序集中的可执行文件,如果不是可执行文件呢?

 

还有另外一种更常用的方式。程序集B:

    class AProgram
    {
        static void Main(string[] args)
        {
            AppDomain currentDomain = AppDomain.CurrentDomain;
            Console.WriteLine(currentDomain.FriendlyName);
            AppDomain secondDomain = AppDomain.CreateDomain("New Domain");
            //secondDomain.ExecuteAssembly("Delegate_Test.exe");
            secondDomain.CreateInstance("Delegate_Test", "Assemblies_Test.Demo", true, BindingFlags.CreateInstance, null, new object[] { 2, 5 }, null, null);
            Console.ReadLine();
        }
    }
public ObjectHandle CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes);

CreateInstance 返回的是 ObjectHandle,并不是实例。

进一步调用 Unwrap 方法返回背后的代理对象:

            var results = secondDomain.CreateInstance("Delegate_Test", "Assemblies_Test.Demo", true, BindingFlags.CreateInstance, null, new object[] {2, 5}, null, null);
            var assemblies_Test = results.Unwrap() as Assemblies_Test.Demo;
            assemblies_Test.hello();

 

3. 程序集卸载

  在主应用程序域中创建 新的应用程序域,并加载所需的程序集,在主应用程序域中,卸载新的域,就完成了程序集的卸载了。

程序集与应用程序域基础练习

标签:

原文地址:http://www.cnblogs.com/Daniel-Liang/p/5778151.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!