using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Reflection; using Autofac; using Autofac.Builder; using Autofac.Core; using Chernobyl.Destruction; using Chernobyl.Extensions.Configuration; using Chernobyl.Plugin; namespace Chernobyl.Dependency.Autofac { /// /// Dependency specific extensions using autofac. /// public static class AutofacExt { /// /// Loads the Autofac modules and Chernobyl plugins using the /// provided. Modules and plugins from the calling assembly will also be included. /// /// The instance that loads the plugins. /// The received after calling /// and the Chernobyl plugins /// found from the Autofac modules. Make sure to dispose of these instances when shutting /// down the application or unloading the plugin. public static (IContainer, IEnumerable>) LoadPlugins(this ContainerBuilder builder) { var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); var pluginAssemblies = config.GetPluginAssemblies().Append(Assembly.GetCallingAssembly()).ToArray(); builder.RegisterAssemblyModules(pluginAssemblies); var container = builder.Build(); return (container, container.Resolve>().Select(plugin => new TryDisposable(plugin)).ToArray()); } /// /// Binds the type as a plugin. Typically plugin are constructed at /// application startup and disposed at application shutdown. /// public static void BindPlugin(this ContainerBuilder builder) { builder.RegisterType().AsSelf().SingleInstance(); builder.RegisterType>().As().SingleInstance(); } /// /// Returns a predicate that returns true when the type is of . /// public static Func TypePredicate() => (param, ctx) => param.ParameterType == typeof(T); /// /// Returns a method that uses the context to resolve the service named . /// public static Func NamedAccessor(string serviceName) => (param, ctx) => ctx.ResolveNamed(serviceName); } /// /// Resolves a service of the specified parameter and of type into a /// parameter of the same type. /// /// The type of the parameter to inject into and the type of the service to /// inject into that parameter. public class Param : ResolvedParameter { /// public Param(string serviceName) : base(AutofacExt.TypePredicate(), AutofacExt.NamedAccessor(serviceName)) {} } }