3.程序集与动态编程的应用, 要求对一个具体问题进行分析, 并给出一个解决方案.4. 桌面应用: 简单控件的使用(观察者模式)

解决方案 »

  1.   

    (1)Client端Emit动态程序集(Dynamic Assembly)完成后,将Dynamic Assembly保持到一个字典中,并再将其保存到一个本地的临时文件。
     private IDictionary<string, Assembly> assemblyDictionary = new Dictionary<string, Assembly>(); //Client保持动态程序集
    AssemblyBuilder dynamicAssembly;
    //
    this.assemblyDictionary.Add(entityType.Assembly.FullName, entityType.Assembly);            
    dynamicAssembly.Save("temp.dll");(2)将temp.dll文件读入到内存的buffer中,然后就可以删除临时文件了。
     byte[] asmBuff = FileHelper.ReadFileReturnBytes("temp.dll");
    FileHelper.DeleteFile("temp.dll");(3)将asmBuff传递到Server端,Server端则可以从byte[]加载程序集,并将加载的程序集保持到一个字典中:
     private IDictionary<string, Assembly> assemblyDictionary = new Dictionary<string, Assembly>(); //Server保持动态程序集
    //
    Assembly asm = AppDomain.CurrentDomain.Load(assBuff);
    assemblyDictionary.Add(asm.FullName, asm);(4)如此一来,Client和Server都保持了Dynamic Assembly的引用,但是,这还不够,在后续使用动态程序集的时候,会抛出类似“未能加载...程序集”的异常。所以,我们在Client和Server端都要通过预定AppDomain.CurrentDomain.AssemblyResolve事件来处理动态程序集加载失败的情况:
             AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); //处理动态程序集加载失败的情况           Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
            {
                if (this.assemblyDictionary.ContainsKey(args.Name))
                {
                    return this.assemblyDictionary[args.Name];
                }
                return null;
            }       再做完上述这些步骤之后,我们就可以在Client和Server端都正常的使用动态程序集了。
      

  2.   

    using System.CodeDom;
    using System.CodeDom.Compiler;
    using Microsoft.CSharp;
    using System.Reflection;class Program
    {
        static void Main(string[] args)
        {
            ICodeCompiler compiler = new CSharpCodeProvider().CreateCompiler();//得到一个CSharp的编译器
            CompilerParameters cp = new CompilerParameters();
            cp.ReferencedAssemblies.Add("system.dll");
            cp.ReferencedAssemblies.Add("system.data.dll");
            cp.ReferencedAssemblies.Add("system.xml.dll");
            cp.GenerateExecutable = false;//这是指示说我们输出的程序集是dll,而不是exe
            cp.GenerateInMemory = true; //这是指示在内存中建立该程序集        StringBuilder sb = new StringBuilder();
            sb.Append("using System; \n");
            sb.Append("public class MyClass{");
            sb.Append("public string HelloWorld(){");
            sb.AppendFormat("return {0};", "\"Hello,world\"");
            sb.Append("}}"); //这里为止,我们构造了一个动态的类型,它有一个要领是HelloWorld        CompilerResults result = compiler.CompileAssemblyFromSource(cp, sb.ToString()); //执行编译        object _compilerobject = result.CompiledAssembly.CreateInstance("MyClass");        MethodInfo method = _compilerobject.GetType().GetMethod("HelloWorld");
            Console.WriteLine(method.Invoke(_compilerobject, null).ToString());        Console.Read();
        }
    }