部分内容请参考前一篇文章如何自定义一个自己的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 };
}
else if (item.Type.IsInterface)
{
subs = types.Where(t => t.IsClass && t.GetInterfaces().Contains(item.Type)).ToList();
}
foreach (var type in subs)
{
var @inject = type.GetCustomAttribute<InjectAttribute>();
if (@inject == null) @inject = new InjectAttribute();
if (!type.IsGenericType && !type.ContainsGenericParameters && !type.GetGenericArguments().Any())
{
if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Instance)
{
RegistInstance(builder, @inject.Named, type, item.Type);
}
else if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Scoped)
{
RegistScoped(builder, @inject.Named, type, item.Type);
}
else if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Single)
{
RegistSingle(builder, @inject.Named, type, item.Type);
}
else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Instance)
{
RegistInstance(builder, type, item.Type);
}
else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Scoped)
{
RegistScoped(builder, type, item.Type);
}
else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Single)
{
RegistSingle(builder, type, item.Type);
}
}
else
{
// 增加泛型支持
if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Instance)
{
RegistInstanceGeneric(builder, @inject.Named, type, item.Type);
}
else if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Scoped)
{
RegistScopedGeneric(builder, @inject.Named, type, item.Type);
}
else if (item.Kind == InjectKind.Named && @inject.Scope == InjectScope.Single)
{
RegistSingleGeneric(builder, @inject.Named, type, item.Type);
}
else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Instance)
{
RegistInstanceGeneric(builder, type, item.Type);
}
else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Scoped)
{
RegistScopedGeneric(builder, type, item.Type);
}
else if (item.Kind == InjectKind.Typed && @inject.Scope == InjectScope.Single)
{
RegistSingleGeneric(builder, type, item.Type);
}
}
}
}
}
public static void RegistSingle(ContainerBuilder builder, Type implType, Type type)
{
builder.RegisterType(implType)
.As(type)
.AsImplementedInterfaces()
.SingleInstance()
.PropertiesAutowired();
}
public static void RegistSingleGeneric(ContainerBuilder builder, Type implType, Type type)
{
builder.RegisterGeneric(implType)
.As(type)
.AsImplementedInterfaces()
.SingleInstance()
.PropertiesAutowired();
}
public static void RegistInstance(ContainerBuilder builder, Type implType, Type type)
{
builder.RegisterType(implType)
.As(type)
.AsImplementedInterfaces()
.InstancePerDependency()
.PropertiesAutowired();
}
public static void RegistInstanceGeneric(ContainerBuilder builder, Type implType, Type type)
{
builder.RegisterGeneric(implType)
.As(type)
.AsImplementedInterfaces()
.InstancePerDependency()
.PropertiesAutowired();
}
public static void RegistScoped(ContainerBuilder builder, Type implType, Type type)
{
builder.RegisterType(implType)
.As(type)
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.PropertiesAutowired();
}
public static void RegistScopedGeneric(ContainerBuilder builder, Type implType, Type type)
{
builder.RegisterGeneric(implType)
.As(type)
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.PropertiesAutowired();
}
public static void RegistSingle(ContainerBuilder builder, string named, Type implType, Type type)
{
builder.RegisterType(implType)
.Named(named, type)
.AsImplementedInterfaces()
.SingleInstance()
.PropertiesAutowired();
builder.RegisterType(type)
.AsSelf()
.AsImplementedInterfaces()
.SingleInstance()
.PropertiesAutowired();
}
public static void RegistSingleGeneric(ContainerBuilder builder, string named, Type implType, Type type)
{
builder.RegisterGeneric(implType)
.Named(named, type)
.AsImplementedInterfaces()
.SingleInstance()
.PropertiesAutowired();
builder.RegisterGeneric(type)
.AsSelf()
.AsImplementedInterfaces()
.SingleInstance()
.PropertiesAutowired();
}
public static void RegistInstance(ContainerBuilder builder, string named, Type implType, Type type)
{
builder.RegisterType(implType)
.Named(named, type)
.AsImplementedInterfaces()
.InstancePerDependency()
.PropertiesAutowired();
builder.RegisterType(type)
.AsSelf()
.AsImplementedInterfaces()
.InstancePerDependency()
.PropertiesAutowired();
}
public static void RegistInstanceGeneric(ContainerBuilder builder, string named, Type implType, Type type)
{
builder.RegisterGeneric(implType)
.Named(named, type)
.AsImplementedInterfaces()
.InstancePerDependency()
.PropertiesAutowired();
builder.RegisterGeneric(type)
.AsSelf()
.AsImplementedInterfaces()
.InstancePerDependency()
.PropertiesAutowired();
}
public static void RegistScoped(ContainerBuilder builder, string named, Type implType, Type type)
{
builder.RegisterType(implType)
.Named(named, type)
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.PropertiesAutowired();
builder.RegisterType(type)
.AsSelf()
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.PropertiesAutowired();
}
public static void RegistScopedGeneric(ContainerBuilder builder, string named, Type implType, Type type)
{
builder.RegisterGeneric(implType)
.Named(named, type)
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.PropertiesAutowired();
builder.RegisterGeneric(type)
.AsSelf()
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.PropertiesAutowired();
}
}
}
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetExtensions.Core.Autofac
{
public static class AutofacExtensions
{
public static IApplicationBuilder UseAutofac(this IApplicationBuilder app, RegistTypeResolver resolver)
{
resolver.LifetimeScope = app.ApplicationServices.GetAutofacRoot();
return app;
}
}
}
在Startup.cs文件中添加以下代码
覆盖NetCore自身的IOC容器工厂类Program.cs
using Autofac;
using Autofac.Core;
using System;
using System.Collections.Generic;
using System.Text;
namespace DotNetExtensions.Core.Autofac
{
public class RegistTypeResolver : Singleton<RegistTypeResolver>
{
private RegistTypeResolver() { }
public ILifetimeScope LifetimeScope { get; set; }
public T Resolve<T>()
{
if (LifetimeScope == null || !LifetimeScope.IsRegistered(typeof(T))) throw new Exception($"Type [{typeof(T)}] not registed");
return LifetimeScope.Resolve<T>();
}
public object Resolve(Type type)
{
if (LifetimeScope == null || !LifetimeScope.IsRegistered(type)) throw new Exception($"Type [{type.FullName}] not registed");
return LifetimeScope.Resolve(type);
}
public object Resolve(Type type, params Parameter[] parameters)
{
if (LifetimeScope == null || !LifetimeScope.IsRegistered(type)) throw new Exception($"Type [{type.FullName}] not registed");
return LifetimeScope.Resolve(type, parameters);
}
public object ResolveNamed(string name, Type type)
{
if (LifetimeScope == null || !LifetimeScope.IsRegisteredWithName(name, type)) throw new Exception($"Named [{name}] with type [{type.FullName}] not registed");
return LifetimeScope.ResolveNamed(name, type);
}
public object ResolveNamed(string name, Type type, params Parameter[] parameters)
{
if (LifetimeScope == null || !LifetimeScope.IsRegisteredWithName(name, type)) throw new Exception($"Named [{name}] with type [{type.FullName}] not registed");
return LifetimeScope.ResolveNamed(name, type, parameters);
}
public T ResolveNamed<T>(string name) where T : class, new()
{
if (LifetimeScope == null || !LifetimeScope.IsRegisteredWithName(name, typeof(T))) throw new Exception($"Named [{name}] with type [{typeof(T).FullName}] not registed");
return (T)LifetimeScope.ResolveNamed(name, typeof(T));
}
public T ResolveNamed<T>(string name, params Parameter[] parameters) where T : class, new()
{
if (LifetimeScope == null || !LifetimeScope.IsRegisteredWithName(name, typeof(T))) throw new Exception($"Named [{name}] with type [{typeof(T).FullName}] not registed");
return (T)LifetimeScope.ResolveNamed(name, typeof(T), parameters);
}
public T Resolve<T>(params Parameter[] parameters)
{
if (LifetimeScope == null || !LifetimeScope.IsRegistered(typeof(T))) throw new Exception($"Type [{typeof(T)}] not registed");
return LifetimeScope.Resolve<T>(parameters);
}
}
}
最后只需要在要注入的类或者接口上添加[AutoInject]注解即可
using DotNetExtensions.Core.IOC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CoreSimple.IOC
{
public class IOC_Simple
{
public IOC_Simple()
{
var start = DateTime.Now;
ContainerBuilder builder = ContainerBuilder.Default;
builder.RegistTypes(option =>
{
option.Assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies());
option.Filters.Add(new InjectTypeFilter
{
Kind = InjectKind.Named,
Type = typeof(IProvider)
});
});
Console.WriteLine($"{(DateTime.Now -start).TotalMilliseconds}/ms");
Timer timer = new Timer(new TimerCallback(obj =>
{
var provider = builder.Resolve<IProvider>();
provider.Write();
var provider2 = builder.Resolve<IProvider2>();
provider2.Write();
//var provider3 = builder.Resolve<Provider3>();
//provider3.Write();
var provider31 = builder.ResolveNamed<Provider3>("CoreSimple.IOC.Provider3");
provider31.Write();
// 如果不指定名称 则使用类全名称 = typeof(Provider1).FullName
//var provider2 = builder.ResolveNamed<IProvider>("Provider1");
//provider2.Write();
//var provider1 = builder.ResolveNamed<IProvider>("Provider2");
//provider1.Write();
}), null, 1000, 1000);
}
}
public interface IProvider : IAutoInject
{
void Write();
}
[AutoInject(Kind = InjectKind.Typed)]
public interface IProvider2
{
void Write();
}
public class Provider1 : IProvider
{
public void Write()
{
Console.WriteLine("I'm is provider 1");
}
}
public class Provider2 : IProvider2
{
public void Write()
{
Console.WriteLine("I'm is provider 2");
}
}
[AutoInject(InjectKind.Named)]
public class Provider3
{
public void Write()
{
Console.WriteLine("I'm is provider 3");
}
}
}