2

I've got a rather large (and growing) application that uses Nancy and subsequently the TinyIoC library. Each of the modules are broken out into individual projects, along with my data models, so my project structure looks sort-of like this:

Solution
  |- NancyHost
  |- DataModels
  |- Modules.Common
  |- Modules.Dashboard
  |- Modules.Security
  |- Repositories

The issue that I'm having is TinyIoC has an AutoRegister event that is supposed to go through the current AppDomain and register all the "register-able" types. This is great except that on startup the assemblies are not yet loaded into the app domain since it uses DI to resolve types.

As a work-around I've come up with classes like this:

public static class RepositoryInitializer
{
    public static void Initialize()
    {

    }
}

Which I then call from the Main on startup, but I don't really like that approach since it requires me to make a dummy initializer class for each linked assembly. I could also do something like:

GC.KeepAlive(typeof(ReferencedAssembly.SomeType));

But again, that requires me to add that same directive for each referenced assembly.

I thought I remember something about a hard-binding attribute you could apply to the assembly that would pre-load a referenced assembly? I can't find anything on it but I swear it was there.

I also tried this:

    static void Preload()
    {
        string location = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        List<Type> types = new List<Type>();
        foreach (var dllFile in Directory.EnumerateFiles(location, "*.dll"))
        {
            types.AddRange(Assembly.ReflectionOnlyLoadFrom(dllFile).GetTypes());
        }

        var assemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();

        //assemblies does not contain all referenced assemblies
    }

Because I read something about using ReflectionOnlyLoadFrom that would cause the DLL to load, but this gives me an exception about having to preload other referenced DLL's to be able to reflect the types (like System.Core).

So the question is, how can I preload my referenced assemblies without using explicit references to the types they contain? Please note that Assembly.GetReferencedAssemblies only contains the loaded assemblies, not all the referenced ones.

This is somewhat duplicate, but not any help: Preload assemblies: referenced, unreferenced, not loaded until they are needed

Edit Here is a version with Assembly.Load:

    static void Preload()
    {
        string location = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        var assemblies = new List<Assembly>();

        foreach (var dllFile in Directory.EnumerateFiles(location, "*.dll"))
        {
            assemblies.Add(Assembly.Load(new AssemblyName() { CodeBase = dllFile }));
            //Also tried Assembly.Load(File.ReadAllBytes(dllFile)), same effect
        }

        var refAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
    }

It does load the assemblies into the assemblies list, but does not cause them to be loaded into the current app domain. (Assembly.GetReferencedAssemblies() returns the same before and after the Preload call).

Community
  • 1
  • 1
Ron Beyer
  • 11,003
  • 1
  • 19
  • 37
  • `Assembly.Load` is what you actually want. – SLaks Aug 25 '15 at 21:40
  • @SLaks How do I load it into the current app domain? All the `Assembly.Load` overloads take an assembly name, assuming I don't have all of them hard-coded, how do I figure out which ones are referenced by the executable? – Ron Beyer Aug 25 '15 at 21:42
  • Just construct an `AssemblyName` from each DLL filename. – SLaks Aug 25 '15 at 21:53
  • @SLaks Am I supposed to do something special with the returned assembly? The `Assembly.Load(byte[])` says that it gets loaded into the callers app domain, but (see my edit), it doesn't look like it does since the call to `GetReferencedAssemblies()` is the same before and after `Preload`. – Ron Beyer Aug 25 '15 at 22:03
  • `GetReferencedAssemblies()` returns all references _that your assembly uses_. Unused references are stripped at compile-time. Loading assemblies will never change the result of `GetReferencedAssemblies()`. – SLaks Aug 26 '15 at 02:17

0 Answers0