So I did it like this.  I would have preferred to have injected an IDictionary<string, IShipper>, but because of the limitation with injecting "IEnumerable" into the constructor (this limitation is Unity specific), I came up with a little workaround.
public interface IShipper
{
    void ShipOrder(Order ord);
    string FriendlyNameInstance { get;} /* here for my "trick" */
}
public interface IOrderProcessor
{
    void ProcessOrder(String preferredShipperAbbreviation, Order ord);
}
public class Order
{
}
public class FedExShipper : IShipper
{
    private readonly Common.Logging.ILog logger;
    public static readonly string FriendlyName = typeof(FedExShipper).FullName; /* here for my "trick" */
    public FedExShipper(Common.Logging.ILog lgr)
    {
        if (null == lgr)
        {
            throw new ArgumentOutOfRangeException("Log is null");
        }
        this.logger = lgr;
    }
    public string FriendlyNameInstance => FriendlyName; /* here for my "trick" */
    public void ShipOrder(Order ord)
    {
        this.logger.Info("I'm shipping the Order with FedEx");
    }
public class UpsShipper : IShipper
{
    private readonly Common.Logging.ILog logger;
    public static readonly string FriendlyName = typeof(UpsShipper).FullName; /* here for my "trick" */
    public UpsShipper(Common.Logging.ILog lgr)
    {
        if (null == lgr)
        {
            throw new ArgumentOutOfRangeException("Log is null");
        }
        this.logger = lgr;
    }
    public string FriendlyNameInstance => FriendlyName; /* here for my "trick" */
    public void ShipOrder(Order ord)
    {
        this.logger.Info("I'm shipping the Order with Ups");
    }
}
public class UspsShipper : IShipper
{
    private readonly Common.Logging.ILog logger;
    public static readonly string FriendlyName = typeof(UspsShipper).FullName; /* here for my "trick" */
    public UspsShipper(Common.Logging.ILog lgr)
    {
        if (null == lgr)
        {
            throw new ArgumentOutOfRangeException("Log is null");
        }
        this.logger = lgr;
    }
    public string FriendlyNameInstance => FriendlyName; /* here for my "trick" */
    public void ShipOrder(Order ord)
    {
        this.logger.Info("I'm shipping the Order with Usps");
    }
}
public class OrderProcessor : IOrderProcessor
{
    private Common.Logging.ILog logger;
    //IDictionary<string, IShipper> shippers; /*   :(    I couldn't get IDictionary<string, IShipper>  to work */
    IEnumerable<IShipper> shippers;
    public OrderProcessor(Common.Logging.ILog lgr, IEnumerable<IShipper> shprs)
    {
        if (null == lgr)
        {
            throw new ArgumentOutOfRangeException("Log is null");
        }
        if (null == shprs)
        {
            throw new ArgumentOutOfRangeException("ShipperInterface(s) is null");
        }
        this.logger = lgr;
        this.shippers = shprs;
    }
    public void ProcessOrder(String preferredShipperAbbreviation, Order ord)
    {
        this.logger.Info(String.Format("About to ship. ({0})", preferredShipperAbbreviation));
        /* below foreach is not needed, just "proves" everything was injected */
        foreach (IShipper sh in shippers)
        {
            this.logger.Info(String.Format("ShipperInterface . ({0})", sh.GetType().Name));
        }
        IShipper foundShipper = this.FindIShipper(preferredShipperAbbreviation);
        foundShipper.ShipOrder(ord);
    }
    private IShipper FindIShipper(String preferredShipperAbbreviation)
    {
        IShipper foundShipper = this.shippers.FirstOrDefault(s => s.FriendlyNameInstance.Equals(preferredShipperAbbreviation, StringComparison.OrdinalIgnoreCase));
        if (null == foundShipper)
        {
            throw new ArgumentNullException(
                String.Format("ShipperInterface not found in shipperProviderMap. ('{0}')", preferredShipperAbbreviation));
        }
        return foundShipper;
    }
}
And calling code: (that would be in something like "Program.cs" for example)
Common.Logging.ILog log = Common.Logging.LogManager.GetLogger(typeof(Program));
IUnityContainer cont = new UnityContainer();
cont.RegisterInstance<ILog>(log);
cont.RegisterType<IShipper, FedExShipper>(FedExShipper.FriendlyName);
cont.RegisterType<IShipper, UspsShipper>(UspsShipper.FriendlyName);
cont.RegisterType<IShipper, UpsShipper>(UpsShipper.FriendlyName);
cont.RegisterType<IOrderProcessor, OrderProcessor>();
Order ord = new Order();
IOrderProcessor iop = cont.Resolve<IOrderProcessor>();
iop.ProcessOrder(FedExShipper.FriendlyName, ord);
Logging Output:
2018/09/21 08:13:40:556 [INFO]  MyNamespace.Program - About to ship. (MyNamespace.Bal.Shippers.FedExShipper)
2018/09/21 08:13:40:571 [INFO]  MyNamespace.Program - ShipperInterface . (FedExShipper)
2018/09/21 08:13:40:572 [INFO]  MyNamespace.Program - ShipperInterface . (UspsShipper)
2018/09/21 08:13:40:572 [INFO]  MyNamespace.Program - ShipperInterface . (UpsShipper)
2018/09/21 08:13:40:573 [INFO]  MyNamespace.Program - I'm shipping the Order with FedEx
So each concrete has a static string providing its name in a strong-typed fashion. ("FriendlyName")
And then I have an instance string-get property which uses the exact same value to keep things in sync. ("FriendlyNameInstance")
By forcing the issue by using a property on the Interface (below partial code)
public interface IShipper
{
   string FriendlyNameInstance { get;}
}
I can use this to "find" my shipper out of the collection of shippers.
The internal method "FindIShipper" is the kinda-factory, but removes the need to have a separate IShipperFactory and ShipperFactory interface and class.  Thus simplifying the overall setup.  And still honors Constructor-Injection and Composition root.
If anyone knows how to use IDictionary<string, IShipper> (and inject via the constructor), please let me know.
But my solution works... with a little razzle dazzle.
My third-party-dll dependency list. (I'm using dotnet core, but dotnet framework with a semi new version of Unity should work too).  (See PackageReference's below)
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Common.Logging" Version="3.4.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.1.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
    <PackageReference Include="Unity" Version="5.8.11" />
  </ItemGroup>
  <ItemGroup>
    <None Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>
</Project>
APPEND:
Here is the autofac version:
(using all the same interfaces and concretes above )
Program.cs
namespace MyCompany.ProofOfConcepts.AutofacStrategyPatternExample.DemoCommandLineInterfaceOne
{
    using System;
    using System.Text;
    using Autofac;
    using Autofac.Extensions.DependencyInjection;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    /* need usings for all the object above */
    using MyCompany.ProofOfConcepts.AutofacStrategyPatternExample.Domain;
    using NLog;
    using NLog.Extensions.Logging;
    public class Program
    {
        private static Logger programStaticLoggerThatNeedsToBeInitiatedInMainMethod = null;
        public static int Main(string[] args)
        {
            Logger loggerFromNLogLogManagerGetCurrentClassLogger = NLog.LogManager.GetCurrentClassLogger(); /* if this is made a private-static, it does not log the entries */
            programStaticLoggerThatNeedsToBeInitiatedInMainMethod = loggerFromNLogLogManagerGetCurrentClassLogger;
            programStaticLoggerThatNeedsToBeInitiatedInMainMethod.Info("programStaticLoggerThatNeedsToBeInitiatedInMainMethod: Main.Start");
            try
            {
                bool useCodeButNotAutofacJson = true; /* true will "code up" the DI in c# code, false will kick in the autofac.json */
                string autoFacFileName = useCodeButNotAutofacJson ? "autofac.Empty.json" : "autofac.json"; /* use "empty" to prove the DI is not coming from non-empty json */
                programStaticLoggerThatNeedsToBeInitiatedInMainMethod.Info(string.Format("programStaticLoggerThatNeedsToBeInitiatedInMainMethod: autoFacFileName={0}", autoFacFileName));
                IConfiguration config = new ConfigurationBuilder()
                    .SetBasePath(System.IO.Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                    .AddJsonFile(autoFacFileName)
                    .Build();
                IServiceProvider servicesProvider = BuildDi(config, useCodeButNotAutofacJson);
                using (servicesProvider as IDisposable)
                {
                    IOrderProcessor processor = servicesProvider.GetRequiredService<IOrderProcessor>();
                    processor.ProcessOrder(FedExShipper.FriendlyName, new Order());
                    Microsoft.Extensions.Logging.ILogger loggerFromIoc = servicesProvider.GetService<ILoggerFactory>()
                    .CreateLogger<Program>();
                    loggerFromIoc.LogInformation("loggerFromIoc:Starting application");
                    loggerFromIoc.LogInformation("loggerFromIoc:All done!");
                    Console.WriteLine("Press ANY key to exit");
                    Console.ReadLine();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(GenerateFullFlatMessage(ex));
                //// NLog: catch any exception and log it.
                programStaticLoggerThatNeedsToBeInitiatedInMainMethod.Error(ex, "programStaticLoggerThatNeedsToBeInitiatedInMainMethod : Stopped program because of exception");
                throw;
            }
            finally
            {
                // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
                LogManager.Shutdown();
            }
            Console.WriteLine("Returning 0 and exiting.");
            return 0;
        }
        private static IServiceProvider BuildDi(IConfiguration config, bool useCodeButNotAutofacJson)
        {
            NLog.Extensions.Logging.NLogProviderOptions nlpopts = new NLog.Extensions.Logging.NLogProviderOptions
            {
                IgnoreEmptyEventId = true,
                CaptureMessageTemplates = true,
                CaptureMessageProperties = true,
                ParseMessageTemplates = true,
                IncludeScopes = true,
                ShutdownOnDispose = true
            };
            IServiceCollection sc = new ServiceCollection()
            ////.AddLogging(loggingBuilder =>
            ////{
            ////    // configure Logging with NLog
            ////    loggingBuilder.ClearProviders();
            ////    loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
            ////    loggingBuilder.AddNLog(config);
            ////})
            .AddLogging(loggingBuilder =>
            {
                ////use nlog
                loggingBuilder.AddNLog(nlpopts);
                NLog.LogManager.LoadConfiguration("nlog.config");
            })
            .AddSingleton<IConfiguration>(config);
            //// // /* before autofac */   return sc.BuildServiceProvider();
            //// Create a container-builder and register dependencies
            Autofac.ContainerBuilder builder = new Autofac.ContainerBuilder();
            // Populate the service-descriptors added to `IServiceCollection`
            // BEFORE you add things to Autofac so that the Autofac
            // registrations can override stuff in the `IServiceCollection`
            // as needed
            builder.Populate(sc);
            if (useCodeButNotAutofacJson)
            {
                programStaticLoggerThatNeedsToBeInitiatedInMainMethod.Info("Coding up Autofac DI");
                /* "Keyed" is not working, do not use below */
                ////builder.RegisterType<FedExShipper>().Keyed<IShipper>(FedExShipper.FriendlyName);
                ////builder.RegisterType<UpsShipper>().Keyed<IShipper>(UpsShipper.FriendlyName);
                ////builder.RegisterType<UspsShipper>().Keyed<IShipper>(UspsShipper.FriendlyName);
                builder.RegisterType<FedExShipper>().As<IShipper>();
                builder.RegisterType<UpsShipper>().As<IShipper>();
                builder.RegisterType<UspsShipper>().As<IShipper>();
                builder.RegisterType<OrderProcessor>().As<IOrderProcessor>();
            }
            else
            {
                programStaticLoggerThatNeedsToBeInitiatedInMainMethod.Info("Using .json file to define Autofac DI");
                // Register the ConfigurationModule with Autofac.
                var module = new Autofac.Configuration.ConfigurationModule(config);
                builder.RegisterModule(module);
            }
            Autofac.IContainer autofacContainer = builder.Build();
            // this will be used as the service-provider for the application!
            return new AutofacServiceProvider(autofacContainer);
        }
        private static string GenerateFullFlatMessage(Exception ex)
        {
            return GenerateFullFlatMessage(ex, false);
        }
        private static string GenerateFullFlatMessage(Exception ex, bool showStackTrace)
        {
            string returnValue;
            StringBuilder sb = new StringBuilder();
            Exception nestedEx = ex;
            while (nestedEx != null)
            {
                if (!string.IsNullOrEmpty(nestedEx.Message))
                {
                    sb.Append(nestedEx.Message + System.Environment.NewLine);
                }
                if (showStackTrace && !string.IsNullOrEmpty(nestedEx.StackTrace))
                {
                    sb.Append(nestedEx.StackTrace + System.Environment.NewLine);
                }
                if (ex is AggregateException)
                {
                    AggregateException ae = ex as AggregateException;
                    foreach (Exception flatEx in ae.Flatten().InnerExceptions)
                    {
                        if (!string.IsNullOrEmpty(flatEx.Message))
                        {
                            sb.Append(flatEx.Message + System.Environment.NewLine);
                        }
                        if (showStackTrace && !string.IsNullOrEmpty(flatEx.StackTrace))
                        {
                            sb.Append(flatEx.StackTrace + System.Environment.NewLine);
                        }
                    }
                }
                nestedEx = nestedEx.InnerException;
            }
            returnValue = sb.ToString();
            return returnValue;
        }
    }
}
autofac.Empty.json  (set to copy always)
{}
autofac.json (set to copy always)
{
  "defaultAssembly": "MyCompany.MyProject",
  "components": [
    {
      "type": "MyCompany.MyProject.Shippers.FedExShipper",
      "services": [
        {
          "type": "MyCompany.MyProject.Shippers.Interfaces.IShipper"
        }
      ]
    },
    {
      "type": "MyCompany.MyProject.Shippers.UpsShipper",
      "services": [
        {
          "type": "MyCompany.MyProject.Shippers.Interfaces.IShipper"
        }
      ]
    },
    {
      "type": "MyCompany.MyProject.Shippers.UspsShipper",
      "services": [
        {
          "type": "MyCompany.MyProject.Shippers.Interfaces.IShipper"
        }
      ]
    },
    {
      "type": "MyCompany.MyProject.Processors.OrderProcessor",
      "services": [
        {
          "type": "MyCompany.MyProject.Processors.Interfaces.IOrderProcessor"
        }
      ]
    }
  ]
}
and csproj
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Autofac" Version="5.1.2" />
    <PackageReference Include="Autofac.Configuration" Version="5.1.0" />
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.2" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.2" />
    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.2" />
    <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.2" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.2" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.2" />
    <PackageReference Include="NLog.Extensions.Logging" Version="1.6.1" />
  </ItemGroup>
From
https://autofaccn.readthedocs.io/en/latest/integration/netcore.html
PS
In the autofac version I had to change the Logger being injected to be a LoggerFactory.
Here is the OrderProcessor alternate version.  You'll have do the same "Microsoft.Extensions.Logging.ILoggerFactory loggerFactory" alternative injection for all 3 concrete "Shipper"'s as well.
namespace MyCompany.MyProject.Processors
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.Extensions.Logging;
    public class OrderProcessor : IOrderProcessor
    {
        ////private readonly IDictionary<string, IShipper> shippers; /*   :(    I couldn't get IDictionary<string, IShipper>  to work */
        private readonly IEnumerable<IShipper> shippers;
        private Microsoft.Extensions.Logging.ILogger<OrderProcessor> logger;
        public OrderProcessor(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, IEnumerable<IShipper> shprs)
        {
            if (null == loggerFactory)
            {
                throw new ArgumentOutOfRangeException("loggerFactory is null");
            }
            if (null == shprs)
            {
                throw new ArgumentOutOfRangeException("ShipperInterface(s) is null");
            }
            this.logger = loggerFactory.CreateLogger<OrderProcessor>();
            this.shippers = shprs;
        }
        public void ProcessOrder(string preferredShipperAbbreviation, Order ord)
        {
            this.logger.LogInformation(string.Format("About to ship. ({0})", preferredShipperAbbreviation));
            /* below foreach is not needed, just "proves" everything was injected */
            int counter = 0;
            foreach (IShipper sh in this.shippers)
            {
                this.logger.LogInformation(string.Format("IEnumerable:ShipperInterface. ({0} of {1}) -> ({2})", ++counter, this.shippers.Count(), sh.GetType().Name));
            }
            IShipper foundShipper = this.FindIShipper(preferredShipperAbbreviation);
            foundShipper.ShipOrder(ord);
        }
        private IShipper FindIShipper(string preferredShipperAbbreviation)
        {
            IShipper foundShipper = this.shippers.FirstOrDefault(s => s.FriendlyNameInstance.Equals(preferredShipperAbbreviation, StringComparison.OrdinalIgnoreCase));
            if (null == foundShipper)
            {
                throw new ArgumentNullException(
                    string.Format("ShipperInterface not found in shipperProviderMap. ('{0}')", preferredShipperAbbreviation));
            }
            return foundShipper;
        }
    }
}
not related to autofac
nlog.config (set to copy always)
<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogFile="MyCompany.MyProject.Nlog.internalLogFile.log"
      internalLogLevel="Info" >
  <!-- the targets to write to -->
  <targets>
    <!-- write logs to file -->
    <target xsi:type="File" name="target1" fileName="MyCompany.MyProject.Nlog.MyConsoleAppProgram.log"
            layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" />
    <target xsi:type="Console" name="target2"
            layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" />
  </targets>
  <!-- rules to map from logger name to target -->
  <rules>
    <logger name="*" minlevel="Trace" writeTo="target1,target2" />
  </rules>
</nlog>
Late 2022 APPEND.
If you need the below code-functionality ( the below code is copied from above) in multiple places...
private IShipper FindIShipper(String preferredShipperAbbreviation)
{
    IShipper foundShipper = this.shippers.FirstOrDefault(s => s.FriendlyNameInstance.Equals(preferredShipperAbbreviation, StringComparison.OrdinalIgnoreCase));
    if (null == foundShipper)
    {
        throw new ArgumentNullException(
            String.Format("ShipperInterface not found in shipperProviderMap. ('{0}')", preferredShipperAbbreviation));
    }
    return foundShipper;
}
Then  you should (AVOID copy and paste) and (prefer to) encapsulate that code into its own "Factory".
If you follow the SOF answer link below..it'll show the basics of creating a "Factory".  (For this answer, you would have an IShipperFactory .. where in the answer below it is called "IDbContextsFactory").  Same idea though.
https://stackoverflow.com/a/74391698/214977