开发者

AssemblyResolve Does not fire

开发者 https://www.devze.com 2023-02-21 22:15 出处:网络
I have an asp.net application. I want to load some assemblies dynamically. this is my code on application start

I have an asp.net application. I want to load some assemblies dynamically.

this is my code on application start

    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.
        }

this code works fine except when a nested c# code calls a class from my dynamic dll Inside an asp.net page (not code-behind)

sample :

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

what should I do now ?

I think If I know When a new AppDomain is created, it may solve my problem.


I really think you are barking up the wrong tree here.

Assembly.Load(byte[]) does "persist" the assembly in the app domain - otherwise, what else would it be doing?

To illustrate the fact it does, try this:

Create a solution with one console application, and one class library, named OtherAssembly.

In the class library, OtherAssembly, add a single class:

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

In the console application, use this as your program:

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();
        }
    }
}

Don't reference OtherAssembly from your main program assembly, instead, compile the solution and manually drop OtherAssembly.dll in the main program's bin folder.

Run the main program. It outputs "Hello World", which it can only have done if the assembly was loaded and retained in memory. You'll note I've been very careful not to give Visual Studio or C# any hint to load this OtherAssembly. No reference was added, the type is not explicitly referenced in C#.

You need to look again at your problem.

[EDIT: in response to you commenting on the fact this is not an ASP.NET application]

OK - I've moved my main program to an ASP.NET web page and tried accessing the assembly both from code behind and the markup - and it works in both situations. I'm sure you are missing something here - it just doesn't make sense that the behaviour of this method - whose job it is to load an assembly into the current app domain - is different in an ASP.NET scenario.

It seems to me there are at least two things to investigate:

  • If it really is a new app domain being created on each call, it would only be because of an unhandled exception in your application. The quickest way to diagnose this is to use SysInternals Process Explorer. Fire it up - add .Net -> Total AppDomains to the list of columns and watch the app domain count for your process (IIS worker process or web dev) as you run your app. If this increases on each call, you've got unhandled exceptions tearing down one AppDomain and forcing another to be created.
  • Are you sure this assembly is really being loaded? When you pass the byte array to Assembly.Load, try also writing it out to disk using FileStream.Write. Open the file in Reflector or some similar tool. Is this the assembly you expected it to be. Is it really being loaded at all, or is it an empty/corrupt array?

I'm not trying to be argumentative, but this really feels like you are looking in the wrong place for the cause of the problem.


I think If I know When a new AppDomain is created, it may solve my problem

You should use AssemblyLoad event. AssemblyResolved occurs when the resolution of assembly is fails


I found that the problem is because Assembly.Load(bytes); does not persist the assembly in appdomain. does any body know how to persist loaded assembly using Assembly.Load(bytes); in appdomain ?

finally I decided to switch to LoadFile method instead of load.

EDIT

Finally I switched from Assemly.Load(byte[]) to Assembly.LoadFile(string).

But it did not correct the problem itself. I have added <%@Assembly name="MyDLL"%> To All of my ASPX files that has markup C# code emebeded.

And This Solved my Problem.

Thanks to your answers. I have voted up answers that helped me, but I can not accept your solutions because no one is not complete enough.

0

精彩评论

暂无评论...
验证码 换一张
取 消