RichieHindle
RichieHindle

Reputation: 281355

How to pick up an sgen-generated XmlSerializer DLL for a DLL rather than an EXE?

I have an executable called ess.exe. I generate an XmlSerializer DLL for it using sgen.exe, and when I run it, it picks up the generated ess.XmlSerializers.dll and all is well.

I also have a DLL called EntrianSourceSearch_14.dll, which is loaded dynamically using Assembly.LoadFrom(DllPathname). If I generate an XmlSerializer DLL for that DLL, it doesn't pick up the generated DLL; instead it falls back to runtime generation of the XML serialization code.

How do I get my DLL to pick up its corresponding generated XmlSerializer DLL?

Edit: I can't put the XmlSerializer DLL into the executable's directory because my DLL is part of a Visual Studio extension - the executable is Visual Studio (devenv.exe), and copying pieces of my product into its directory would probably be seen as anti-social. :-)

Edit to add more context: This is a Visual Studio add-in and extension. It works with all versions of Visual Studio from 2005 to 2017. The bulk of the code is installed into Program Files, and older versions of Visual Studio simply load it from there as an add-in. For newer versions of Visual Studio, which don't support add-ins, there is an extension which is just a loader for those main components in Program Files. That extension uses LoadFrom to load those main components, one of which is EntrianSourceSearch_14.dll.

Upvotes: 3

Views: 614

Answers (1)

Peter Wishart
Peter Wishart

Reputation: 12270

If you already build and deploy a signed serialization assembly, you can add a CurrentlDomain.AssemblyResolve handler while you load and cache the serializers, something like:

    private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        var codeBase = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;
        var serializerPath = Path.Combine(Path.GetDirectoryName(codeBase), new AssemblyName(args.Name).Name + ".dll");
        if (File.Exists(serializerPath))
            return Assembly.LoadFrom(serializerPath);
        else
            return null;
    }

However, I couldn't find an easy way to include the deployment of the serialization assembly in a single-assembly VS extension.

I did find an alternative method that might be preferable. It avoids calling Assembly.LoadFrom directly and some of the assumptions in the above code:

  • Move the code that uses Xml Serialization to a separate assembly
  • For this assembly:
  • Add a Project reference to the above assembly from the extension package
  • Add a Browse.. reference to the built serialization assembly from the extension package

Upvotes: 2

Related Questions