Skip to content

Separate DLL Files

Roy Schroedel edited this page Jan 15, 2020 · 1 revision

The library is compiled for several CPU architectures. This allows the library to be integrated without IDE warnings. The compiler is also instructed to process certain areas differently, which in certain cases can lead to minor performance advantages. In many cases, this can be safely ignored. But it would still be possible to benefit from it on Any CPU platform targets.


Example of using separate DLLs for the Any CPU platform target:

  • Add the file SilDev.CSharpLib.dll to the references of your project
    • Set Copy Local in Properties to False
  • Copy the files SilDev.CSharpLib32.dll and SilDev.CSharpLib64.dll to the location of the compiled binary files
  • Add some code to the Startup object of your project

Code Example:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Xml;

    internal static class Program
    {
        [STAThread]
        private static void Main()
        {
            AppDomain.CurrentDomain.AssemblyResolve += DynamicAssemblyResolve;
            /*
                add your code here...
            */
        }

        /// <summary>
        ///     Loads the required assembly dynamically based on the current process architecture.
        /// </summary>
        private static Assembly DynamicAssemblyResolve(object sender, ResolveEventArgs args)
        {
            var name = args.Name;
            if (!name.StartsWith("SilDev.", StringComparison.Ordinal))
                return null;
            var length = name.IndexOf(',');
            name = name.Substring(0, length);
            return (from dir in GetProbingDirs()
                    select Environment.Is64BitProcess ?
                        Path.Combine(dir, $"{name}64.dll") :
                        Path.Combine(dir, $"{name}32.dll")
                    into path
                    where File.Exists(path)
                    select Assembly.LoadFile(path)).FirstOrDefault();
        }

        /// <summary>
        ///     Enables support for the `probing privatePath` settings through the `MyApplication.exe.config` file.
        /// </summary>
        private static IEnumerable<string> GetProbingDirs()
        {
            var baseDir = AppDomain.CurrentDomain.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar);
            yield return baseDir;

            var configPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            if (!File.Exists(configPath))
                yield break;

            FileStream fileStream = default;
            string xmlEntry;
            try
            {
                const string xpath = "/*[name()='configuration']/*[name()='runtime']/*[name()='assemblyBinding']/*[name()='probing']/@privatePath";
                fileStream = new FileStream(configPath, FileMode.Open);
                using (var xmlReader = XmlReader.Create(fileStream, new XmlReaderSettings()))
                {
                    fileStream = default;
                    var xmlDoc = new XmlDocument
                    {
                        XmlResolver = null
                    };
                    xmlDoc.Load(xmlReader);
                    xmlEntry = (xmlDoc.SelectSingleNode(xpath) as XmlAttribute)?.Value;
                    if (string.IsNullOrWhiteSpace(xmlEntry))
                        throw new ArgumentException();
                }
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch
#pragma warning restore CA1031 // Do not catch general exception types
            {
                yield break;
            }
            finally
            {
                fileStream?.Dispose();
            }

            if (xmlEntry.Contains(";"))
                foreach (var item in xmlEntry.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                    yield return Path.Combine(baseDir, item);
            else
                yield return Path.Combine(baseDir, xmlEntry);
        }
    }
Clone this wiki locally