部分内容请参考前一篇文章如何自定义一个自己的IOC容器 | DotNetExtensions知识点摘要(二
支持泛型注入和反转Class<Type1,Type2,...>,使用的是Autofac的RegisterGeneric方法
using System;
using System.Collections.Generic;
using System.Linq;
using DotNetExtensions.Core.IOC;
using Autofac;
using ContainerBuilder = Autofac.ContainerBuilder;
using System.Reflection;
using System.IO;
namespace DotNetExtensions.Core.Autofac
{
public static class AutofacBuilderExtensions
{
public static void RegistTypes(
this ContainerBuilder builder, Action<BuilderOption> option)
{
BuilderOption builderOptions = new BuilderOption();
option?.Invoke(builderOptions);
if (!builderOptions.Assemblies.Any())
{
builderOptions.Assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().ToList());
}
// load assemblies from pattern
if (builderOptions.Pattern.Any())
{
string execAssemblyPath = Assembly.GetExecutingAssembly().Location;
if (Directory.Exists(execAssemblyPath))
{
List<string> assemblyFiles = new List<string>();
foreach (var pattern in builderOptions.Pattern)
{
string[] files = Directory.GetFiles(execAssemblyPath, pattern);
if (files != null && files.Length > 0) assemblyFiles.AddRange(files);
}
if (assemblyFiles.Any())
{
builderOptions.Assemblies.AddRange(assemblyFiles.Distinct().Select(file => Assembly.LoadFrom(file)));
}
}
}
List<Type> types = builderOptions.Assemblies.SelectMany(a => a.GetTypes()).Distinct().ToList();
// interface | if inherit IAutoInject or use AutoInjectAttribute
List<Type> autoInjectFromInheritTypes = types.Where(t => t.IsInterface && t.GetInterfaces().Contains(typeof(IAutoInject))).Distinct().ToList();
List<Type> autoInjectFormAttrTypes = types.Where(t => t.IsInterface && t.GetCustomAttribute<AutoInjectAttribute>() != null).Distinct().ToList();
if (autoInjectFromInheritTypes.Any() || autoInjectFormAttrTypes.Any())
{
List<Type> autoInjectTypes = autoInjectFromInheritTypes.Union(autoInjectFormAttrTypes).Distinct().ToList();
builderOptions.Filters.AddRange(autoInjectTypes.Select(type => new InjectTypeFilter { Kind = type.GetCustomAttribute<AutoInjectAttribute>()?.Kind ?? InjectKind.Typed, Type = type }));
}
// class | use AutoInjectAttribute
List<Type> autoInjectClassTypes = types.Where(t => t.IsClass && t.GetCustomAttribute<AutoInjectAttribute>() != null).Distinct().ToList();
if (autoInjectClassTypes.Any())
{
builderOptions.Filters.AddRange(autoInjectClassTypes.Select(type => new InjectTypeFilter { Kind = type.GetCustomAttribute<AutoInjectAttribute>().Kind, Type = type }));
}
foreach (var item in builderOptions.Filters)
{
if (item.Type == typeof(IAutoInject)) continue;
if (item.Type == typeof(IDisposable)) continue;
if (item.Type == typeof(object)) continue;
List<Type> subs = null;
if (item.Type.IsClass)
{
// if class | use self
subs = new List<Type> { item.Type };