AssemblyResolve不会触发

时间:2011-04-05 07:41:03

标签: c# asp.net

我有一个asp.net应用程序。我想动态加载一些程序集。

这是我在应用程序启动时的代码

    protected void Application_Start(Object sender, EventArgs e)
        {
            LoadPrivateAssemblies();
        }
    private static void LoadPrivateAssemblies()
        {
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainAssemblyResolve;

            Assembly.Load("MyDLL");
        }
    static Assembly CurrentDomainAssemblyResolve(object sender, ResolveEventArgs args)
        {
            //loads and returns assembly successfully.
        }

这个代码工作正常,除非嵌套的c#代码从我的动态dll中调用一个类在asp.net页面内(不是代码隐藏)

示例:

<%if(MyDLL.TestObject.Value){%>white some ting<%}%>

我现在该怎么办?

我想如果我知道创建一个新的AppDomain,它可能会解决我的问题。

3 个答案:

答案 0 :(得分:2)

我真的认为你在这里咆哮错误的树。

Assembly.Load(byte [])在应用程序域中“持久化”程序集 - 否则,它还会做什么?

为了说明事实,试试这个:

使用一个控制台应用程序和一个名为OtherAssembly的类库创建解决方案。

在类库OtherAssembly中,添加一个类:

namespace OtherAssembly
{
    public class Class1
    {
        public string HelloWorld()
        {
            return "Hello World";
        }
    }
}

在控制台应用程序中,将其用作程序:

public class Program
{
    static void Main(string[] args)
    {
        try
        {
            using (var fs = new FileStream("OtherAssembly.dll", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                var buffer = new byte[fs.Length];
                // load my assembly into a byte array from disk
                fs.Read(buffer, 0, (int) fs.Length);

                // load the assembly in the byte array into the current app domain
                AppDomain.CurrentDomain.Load(buffer);
            }

            // get my type from the other assembly that we just loaded
            var class1 = Type.GetType("OtherAssembly.Class1, OtherAssembly");

            // create an instance of the type
            var class1Instance = class1.GetConstructor(Type.EmptyTypes).Invoke(null);

            // find and invoke the HelloWorld method.
            var hellowWorldMethod = class1.GetMethod("HelloWorld");
            Console.WriteLine(hellowWorldMethod.Invoke(class1Instance, null));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        finally
        {
            Console.ReadLine();
        }
    }
}

不要从主程序集中引用OtherAssembly,而是编译解决方案并手动删除主程序bin文件夹中的OtherAssembly.dll。

运行主程序。它输出“Hello World”,它只能在程序集加载并保留在内存中时才能完成。你会注意到我一直非常小心,不给Visual Studio或C#任何提示来加载这个OtherAssembly。未添加任何引用,该类型未在C#中显式引用。

您需要再次查看您的问题。

[编辑:回应你评论这不是ASP.NET应用程序的事实]

好的 - 我已经将我的主程序移动到ASP.NET网页并尝试从代码隐藏和标记访问程序集 - 它在两种情况下都有效。我确定你在这里遗漏了一些东西 - 这种方法的行为 - 它的工作是将程序集加载到当前应用程序域中 - 在ASP.NET场景中是不同的,这是没有意义的。

在我看来,至少有两件事需要调查:

  • 如果它确实是在每次调用时创建的新应用域,那么只会是因为应用程序中出现未处理的异常。诊断此问题的最快方法是使用SysInternals Process Explorer。启动它 - 添加.Net - &gt;将AppDomains总数添加到列列表中,并在运行应用程序时查看进程(IIS工作进程或Web开发人员)的应用程序域计数。如果每次调用都会增加,那么就会有未处理的例外情况拆除一个AppDomain并强制创建另一个AppDomain。
  • 你确定这个程序集真的被加载了吗?将字节数组传递给Assembly.Load时,请尝试使用FileStream.Write将其写入磁盘。在Reflector或类似工具中打开文件。这是你期望它的装配。它真的被加载了,还是一个空/损坏的数组?

我不是要争论,但这真的感觉你在错误的地方寻找问题的原因。

答案 1 :(得分:1)

  

我想如果我知道什么时候创建一个新的AppDomain,它可以解决我的问题

您应该使用AssemblyLoad事件。当程序集的分辨率失败时会发生AssemblyResolved

答案 2 :(得分:-1)

我发现问题是因为Assembly.Load(bytes);不会在appdomain中保存程序集。是否有人知道如何在appdomain中使用Assembly.Load(bytes);来保持加载的程序集?

最后我决定切换到LoadFile方法而不是加载。

修改

最后,我从Assemly.Load(byte[])切换到Assembly.LoadFile(string)

但它没有纠正问题本身。我已将<%@Assembly name="MyDLL"%>添加到所有具有标记C#代码的ASPX文件中。

这解决了我的问题。

感谢您的回答。我已经投了很多帮助我的答案,但我无法接受你的解决方案,因为没有人不够完整。