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))
{}
}
}