C#无法将AssemblyResolve与CreateInstanceAndUnwrap结合使用 [英] c# Cant get AssemblyResolve working in combination with CreateInstanceAndUnwrap

查看:66
本文介绍了C#无法将AssemblyResolve与CreateInstanceAndUnwrap结合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



在过去的几天里,我一直在努力解决AsssemblyResolve的问题.
我要实现的是一种服务的设置,该服务可以从URL更新和缓存程序集,并且能够在不重新启动服务的情况下创建和卸载AppDomain.
但是我的问题要简单得多,并且我创建了一个最小化的样本来说明我的问题.
1:带有加载程序的控制台exe

Hi
I’ve been struggling for the past couple of days with at problem with AsssemblyResolve.
What I want to achieve is a setup for a service that can update and cache assemblies from a URL, and be able to Create and UnLoad an AppDomain without restarting the service.
But my problem is much simpler, and I have created a minimized sample, which illustrate my problem.
1: a console exe with a Loader

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

namespace TestAppDoms
{
    public static class Loader
    {
        static void Main()
        {
            AppDomain.CurrentDomain.AssemblyResolve += FindAssem;
            Program.GO();
        }

        public static Assembly FindAssem(object sender, ResolveEventArgs args)
        {
            string shortName = new AssemblyName(args.Name).Name;

            using (FileStream fs = File.OpenRead(Path.Combine(@"C:\TestAssem\", shortName + ".dll")))
            {
                byte[] assemBin = new byte[fs.Length];
                fs.Read(assemBin, 0, Convert.ToInt32(fs.Length));
                Assembly Assem = Assembly.Load(assemBin);

                return Assem;
            }
        }
    }

    public class Program
    {
        public static void GO()
        {
            brokerCtrl brkCtrl = new brokerCtrl();
            brkCtrl.Run();
            Console.ReadLine();
        }
    }
}



2:一个dll(象征一个现成的程序集)



2: a dll (symbolizing the a cashed assembly)

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

namespace TestAppDoms
{
    public class brokerCtrl
    {
        public void Run()
        {
            Console.WriteLine("Hello From Ctrl.dll " + AppDomain.CurrentDomain.FriendlyName);
            
            AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
            setup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            AppDomain brokerDom = AppDomain.CreateDomain("b2bBroker", AppDomain.CurrentDomain.Evidence, setup);
            brokerDom.AssemblyResolve += new ResolveEventHandler(brokerDom_AssemblyResolve);
 
            BrokerWrapper brokerProxy = (BrokerWrapper)brokerDom.CreateInstanceAndUnwrap(typeof(BrokerWrapper).Assembly.FullName, typeof(BrokerWrapper).FullName);
            brokerProxy.StartBroker();
            AppDomain.Unload(brokerDom);
            brokerProxy = null;
            
        }

        public static Assembly brokerDom_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string shortName = new AssemblyName(args.Name).Name;
            Console.WriteLine("Hello from brokerDom_AssemblyResolve");

            using (FileStream fs = File.OpenRead(Path.Combine(@"C:\TestAssem\", shortName + ".dll")))
            {
                byte[] assemBin = new byte[fs.Length];
                fs.Read(assemBin, 0, Convert.ToInt32(fs.Length));
                Assembly Assem = Assembly.Load(assemBin);
                return Assem;
            }
        }
    }

    public class BrokerWrapper : MarshalByRefObject
    {
        public override object InitializeLifetimeService()
        {
            return null;
        }
        public void StartBroker()
        {
            Console.WriteLine("Hello From " + AppDomain.CurrentDomain.FriendlyName);
        }

    }
}



当将TestAppDoms.exe和brokerCtrl.dll都放置在同一目录中(CLR可以在探测路径中找到dll时),所有内容都像一个超级按钮.
但是,当我将dll从exe移开(移至C:\ TestAssem \)时,brokerDom.AssemblyResolve + =新的ResolveEventHandler(brokerDom_AssemblyResolve)不会触发-符合预期.

显然我忽略了一些东西.

有人可以帮我解决我的问题吗?

最好,Robert



When both TestAppDoms.exe and brokerCtrl.dll are placed in the same directory (and the CLR can locate the dll in the probing path) everything works like a charm.
But when I move the dll away from the exe (to the C:\TestAssem\ ) The brokerDom.AssemblyResolve += new ResolveEventHandler(brokerDom_AssemblyResolve) never fires - as expected.

Obviously I overlook something.

Can anybody help me solve my problem?

Best, Robert

推荐答案

最后,我找到了一个解决方案. (通过在NutShell中阅读Albahari C#)

首先,我定义了两个应用程序域共享的小组装.


Finally I found a solution. (by reading Albahari C# in a NutShell)

First I defined a small assemby that both appdomains share.


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

namespace TestAppDoms
{
    public interface Ib2bBroker
    {
        void StartBroker();
    }

    public class b2bBrokerLink : MarshalByRefObject
    {
        public static Dictionary<string, Assembly> assemCache;
        static Dictionary<string, byte[]> assemBinCache;

        public b2bBrokerLink()
        {
            assemCache = new Dictionary<string, Assembly>();
        }

        public override object InitializeLifetimeService()
        {
            return null;
        }
        public void InitAssemCache(Dictionary<string, byte[]> _assemBins)
        {
            assemBinCache = _assemBins;
            Console.WriteLine("Assems loaded");
        }

        public static Assembly brokerDom_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string shortName = new AssemblyName(args.Name).Name;
            Console.WriteLine("Hello from brokerDom_AssemblyResolve");

            if (assemCache.ContainsKey(shortName))
                return assemCache[shortName];

            if (assemBinCache.ContainsKey(shortName))
            {
                Assembly assem = Assembly.Load(assemBinCache[shortName]);
                assemCache.Add(shortName,assem);
                return assem;
            }
            return null;
        }
    }
}



接下来修改如下的BrokerCtrl.Run()



Next modified BrokerCtrl.Run() as follows

Console.WriteLine("Hello From New Ctrl.dll " + AppDomain.CurrentDomain.FriendlyName);

AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
setup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
AppDomain brokerDom = AppDomain.CreateDomain("b2bBroker", AppDomain.CurrentDomain.Evidence, setup);
brokerDom.AssemblyResolve += new ResolveEventHandler(b2bBrokerLink.brokerDom_AssemblyResolve);

b2bBrokerLink assemResolver = (b2bBrokerLink)brokerDom.CreateInstanceFromAndUnwrap(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "b2bBrokerLink.dll"), "TestAppDoms.b2bBrokerLink");
Dictionary<string,> assemBinCache = new Dictionary<string,>();
using (FileStream fs = File.OpenRead(Path.Combine(@"C:\TestAssem\", "b2bBroker" + ".dll")))
{
    byte[] assemBin = new byte[fs.Length];
    fs.Read(assemBin, 0, Convert.ToInt32(fs.Length));
    assemBinCache.Add("b2bBroker", assemBin);
}
assemResolver.InitAssemCache(assemBinCache);
Ib2bBroker broker = (Ib2bBroker)brokerDom.CreateInstanceAndUnwrap("b2bBroker", "TestAppDoms.b2bBroker");
broker.StartBroker();
AppDomain.Unload(brokerDom);
assemResolver = null;



启动b2bBrokerLink会创建新的b2bBroker AppDomain,并允许主AppDomain下载最新的程序集版本(作为原始二进制文件),并将assemCache(Direcrory< string,byte []>)推送到b2bBroker AppDomain中. 接下来,使用接口Ib2bBroker启动代理,brokerDom_AssemblyResolve现在将能够将(最新的)程序集加载到新的AppDomain中. 这可能对其他人有用-也许有人有更好的解决方案.



Initiating b2bBrokerLink creates the new b2bBroker AppDomain and allows the main AppDomain download the most recent assembly-versions (as raw binary) and push assemCache (Direcrory<string,byte[]>) into the b2bBroker AppDomain.
Next start the a broker using the inteface Ib2bBroker and the brokerDom_AssemblyResolve will now be able to load the (most recent) assemblies into the new AppDomain.
It might be usefull for someone else - and maybe someone has a better solution.


这篇关于C#无法将AssemblyResolve与CreateInstanceAndUnwrap结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆