-1

I have consulted code on the website http://codeproject.com with the title "Loading Assemblies from Anywhere into a New AppDomain" of Marius Bancila, but I tested the error as in the attached picture, currently, I don't know resolve, hope you help, thank you.

Link Code https://www.codeproject.com/Articles/453778/Loading-Assemblies-from-Anywhere-into-a-New-AppDom#_articleTop

Test

public class Program
{
    [STAThread]
    public static void Main()
    {
        var project = @"D:\Github\BeyConsPlugin\BeyConsProject\bin\x64\Debug\BeyConsRevitProject.dll";//Path to assembly
        var manager = new AssemblyReflectionManager();
        var success = manager.LoadAssembly(project, Guid.NewGuid().ToString());
        if (success)
        {
            var result = manager.Reflect(project, (a) =>
            {
                return a.GetTypes();
            });
            Console.WriteLine(string.Join("\n", result.Select(x => x.Name)));
        }            
        Console.ReadKey();
        manager.UnloadAssembly(project);
    }       
}

Error enter image description here

NhuTruong
  • 11
  • 5
  • Does this answer your question? [Could not load file or assembly or one of its dependencies](https://stackoverflow.com/questions/4469929/could-not-load-file-or-assembly-or-one-of-its-dependencies) –  Nov 07 '20 at 03:09

1 Answers1

1

Assembly Resolver not Set

Marius's code has a bug in AssemblyReflectionProxy with regards that the Assembly Resolver is not set if you call LoadAssembly unlike Reflect<> which does.

Depending on how a child app domain is created, when loading assemblies it might only have access to the folder as specified during creation. If you need to assembly probe elsewhere for the assembly or its dependencies you need a Assembly Resolver. When .NET is looking for an assembly for a domain, it will call your handler as specified in the assemblie's ReflectionOnlyAssemblyResolve event. If not specified or if the resolver fails to locate the assembly, it will bubble up and throw a load fail exception.

I suggest you change the code from:

public class AssemblyReflectionProxy : MarshalByRefObject
{
  private string _assemblyPath;

  public void LoadAssembly(String assemblyPath)
  {
     try
     {
        _assemblyPath = assemblyPath;
        Assembly.ReflectionOnlyLoadFrom(assemblyPath);
     }
     catch (FileNotFoundException)
     {
        // Continue loading assemblies even if an assembly 
        // cannot be loaded in the new AppDomain.
     }
  }

...to:

public class AssemblyReflectionProxy : MarshalByRefObject
{
  private string _assemblyPath;

  public void LoadAssembly(String assemblyPath)
  {
     try
     {
        AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve // <---- add me
             += OnReflectionOnlyResolve; 

        _assemblyPath = assemblyPath;
        Assembly.ReflectionOnlyLoadFrom(assemblyPath);
     }
     catch (FileNotFoundException)
     {
        // Continue loading assemblies even if an assembly 
        // cannot be loaded in the new AppDomain.
     }
  }

You can see this in Sacha's original code that on which Marius based his.

Add Provision for Resolve Paths

The other problem with the code is that both assume that when loading one assembly, any dependent assemblies are in the same folder something that may not always be the case.

Alter AssemblyReflectionProxy to include a list of paths in which to probe:

public List<string> ResolvePaths { get; set; }

Then modify OnReflectionOnlyResolve to resemble the following:

private Assembly OnReflectionOnlyResolve(ResolveEventArgs args, DirectoryInfo directory)
{
     Assembly loadedAssembly =
         AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies()
             .FirstOrDefault(
               asm => string.Equals(asm.FullName, args.Name,
                   StringComparison.OrdinalIgnoreCase));

     if (loadedAssembly != null)
     {
        return loadedAssembly;
     }

    foreach (var tryFolder in ResolvePaths)
    {
        var asmName = args.Name.Split(',');
        var assemblyPath = Path.Combine(tryFolder, asmName[0] + ".dll");

        if (!File.Exists(assemblyPath))
            return null;

         return Assembly.ReflectionOnlyLoadFrom(assemblyPath);
    }
}

What's in a name?

Both articles neglected to point out the fine print when using ReflectionOnlyLoad. Though Sacha did at least mention his code was for a "code generator" I can't help but wonder that both articles with their "Loading Assemblies....into a New AppDomain" are perhaps somewhat subject to interpretation.

The aim of ReflectionOnlyLoad is just that - for reflection. If you load an assembly via this method you cannot execute any code in it. Additionally and somewhat surprising at first to most assembly reflector programmers including me is that calling GetCustomAttributes will also fail (because it attempts to "instantiate" types in the assembly).

If you are writng your own plug-in system in which each plug-in has its own App Domain, the Assembly reflection and load methods are useful for different stages of the plug-in system loading pipeline:

  1. first pass - use ReflectionOnlyLoad as a way to inspect the plug-in to see if it is valid; perhaps you want to run some security checks safe in the knowledge that none of the plug-ins code can run during this phase
  2. second pass - after verifying the plug-in, you can safely Load/LoadFrom the assembly and execute the code
  • I edited like you but still got the error. Don't mind can you edit for me, sorry, I'm not IT. Link code: https://docs.google.com/document/d/1877WMwGVbfw4fXceQuweaxy-hp4U5s10nM5BtUqtHqI/edit?usp=sharing – NhuTruong Nov 07 '20 at 03:50
  • @NhuTruong see _"Add Provision for Resolve Paths"_ update above –  Nov 07 '20 at 06:51
  • Sorry @MickyD, my problem still hasn't been resolved. – NhuTruong Nov 08 '20 at 04:23
  • @NhuTruong please take note of _[Any answer that gets the asker going in the right direction is helpful](https://stackoverflow.com/help/how-to-answer)_. SO isn't meant to be a venue to fix _all the problems_ in _3rd party_ code. Also be aware of _[When is “EDIT”/“UPDATE” appropriate in a post?](https://meta.stackexchange.com/questions/127639/when-is-edit-update-appropriate-in-a-post)_. I quote _[posts need to be standalone, without any history. These sites are not forums,](https://meta.stackexchange.com/questions/127639/when-is-edit-update-appropriate-in-a-post)_. –  Nov 08 '20 at 05:06
  • @NhuTruong I encourage you to first visit Sacha's code and modify it accordingly. The other codebase is more complex and possibly problematic –  Nov 08 '20 at 05:09
  • I have removed the update according to forum regulations because the above part is still unsolved, thank you for helping me. – NhuTruong Nov 08 '20 at 05:18
  • @NhuTruong _"...the above part is still unsolved"_. I disagree. Your question was about the problem when calling `manager.LoadAssembly` which I have pointed out and showed you how to fix it –  Nov 09 '20 at 01:23
  • Do you have the final code for me to reference, the way you suggested it is still not resolved? I still don't understand. – NhuTruong Nov 09 '20 at 02:36
  • @NhuTruong Yes its in the answer above –  Nov 09 '20 at 04:09