在.Net Framwework MVC5的环境下使用autofac,直接上代码
1.我的环境是.Net Framework4.5,MVC5,VS2017
nuget安装autofac:
Install-Package Autofac -version 4.6.2
MVC安装:
Install-Package Autofac.Mvc5 -version 4.0.2
WebApi安装:
Install-Package Autofac.WebApi2 -version 4.3.0
基础准备:
标识类:IBaseFlagService(实现该接口的类我们都需要注入进去)
用户接口:
public interface IUserService : IBaseFlagService
{
string GetCurrentUserId();
string FormatDate(DateTime? date, bool isBegin);
}
用户实现类:
public class UserService : IUserService
{
public string FormatDate(DateTime? date, bool isBegin)
{
if (date.HasValue)
{
string a = "yyyy-MM-dd ";
string b = isBegin ? "00:00:00.000" : "23:59:59.999";
return date.Value.ToString(a + b);
}
return null;
}
public string GetCurrentUserId()
{
return Guid.NewGuid().ToString();
}
}
动作接口:
public interface IActionService:IBaseFlagService
{
string SayHi();
string Action();
}
动作实现类一:猫
public class CatService : IActionService
{
public string Action()
{
return "猫咪卖萌!";
}
public string SayHi()
{
return "喵~";
}
}
动作实现类二:狗
public class DogService : IActionService
{
public string Action()
{
return "憨憨的柯基卖萌!";
}
public string SayHi()
{
return "汪汪汪~";
}
}
在global程序启动时注入autofac:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
IocService.InitAutofac();
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
IocService:
public class IocService
{
public static IContainer Container;
public static void InitAutofac()
{
string dllNameStr = "WebMvcUseAutofac,WebMvcUseAutofacServices";
string a = ",";
var assList = dllNameStr.Split(new string[] { a }, StringSplitOptions.RemoveEmptyEntries).Select(r => Assembly.Load(r)).ToArray();
var baseType = typeof(IBaseFlagService);
var builder = new ContainerBuilder();
//RegisterAuto(builder, assList, baseType);
RegisterCustom(builder, assList, baseType);
RegisterWithMultipleImplements(builder);
builder.RegisterControllers(assList).PropertiesAutowired();//Mvc使用 注意:控制器无法单例注入,必须一次请求,一个实例,无法单例
//builder.RegisterApiControllers(assList).PropertiesAutowired();//WebApi使用,同样,控制器无法单例注入
IocService.Container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(IocService.Container));//Mvc使用
//GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(IocService.Container);//WebApi使用
}
/// <summary>
/// 通过注入,将实现IBaseFlagService接口的所有服务类注入到类本身所实现的接口中
/// </summary>
/// <param name="builder"></param>
/// <param name="assList"></param>
/// <param name="baseType"></param>
private static void RegisterAuto(ContainerBuilder builder, Assembly[] assList, Type baseType)
{
builder.RegisterAssemblyTypes(assList).Where(r => baseType.IsAssignableFrom(r) && r.IsInterface == false)//找到程序集中符合条件的类
.AsSelf().AsImplementedInterfaces()//注入到自己实现的接口中
.SingleInstance()//生命周期:单例
.PropertiesAutowired();//支持属性注入
}
/// <summary>
/// 自己写逻辑注入
/// </summary>
/// <param name="builder"></param>
/// <param name="assList"></param>
/// <param name="baseType"></param>
private static void RegisterCustom(ContainerBuilder builder, Assembly[] assList, Type baseType)
{
//程序集下所有的类
var allTypeList = assList.SelectMany(r => r.GetTypes()).ToList();
var groupTypeList = allTypeList.ToLookup(r => r.Name).Select(r => new { Name = r.Key, Count = r.Count(), List = r.ToArray() }).OrderBy(r => r.Count).ToArray();
//实现了指定接口的类
var allServiceTypeList = allTypeList.FindAll(r => baseType.IsAssignableFrom(r));
//服务类
var serviceTypes = allServiceTypeList.FindAll(r => r.IsInterface == false);
//服务接口(排除掉标签接口)
var iServiceTypes = allServiceTypeList.FindAll(r => r.IsInterface && IsSameType(r, baseType) == false);
string a = ",";
foreach (var serviceType in serviceTypes)
{
//该服务类所实现的接口
var interfaceList = serviceType.GetInterfaces();
var useInterfaceList = interfaceList.Intersect(iServiceTypes).ToArray();
//校验
if (useInterfaceList.Length == 0)
throw new Exception($"服务类{serviceType.Name}没有实现任何接口!");
else if (useInterfaceList.Length > 1)
throw new Exception($"服务类{serviceType.Name}实现的接口数量大于1个:{string.Join(a, useInterfaceList.Select(r => r.Name))}");
//注入操作
builder.RegisterType(serviceType).As(useInterfaceList[0])
.SingleInstance()//单例注入
.PropertiesAutowired();//支持属性注入
}
}
/// <summary>
/// 一个接口多个实现,手动注入(也可以自动注入,通过增加特性来标识,然后读取注入,我这里就不做演示)
/// </summary>
/// <param name="builder"></param>
private static void RegisterWithMultipleImplements(ContainerBuilder builder)
{
builder.RegisterType<CatService>().Named<IActionService>("Cat").PropertiesAutowired();//Named参数只能是string
builder.RegisterType<DogService>().Keyed<IActionService>("Dog").PropertiesAutowired();//这里只是使用Keyed,因为Keyed参数是object,可以使用枚举
}
public static bool IsSameType(Type type1, Type type2)
{
return type1.FullName == type2.FullName;
}
}
测试代码:
public class HomeController : Controller
{
//构造函数注入
public IUserService _UserServiceForConstructor;
public HomeController(IUserService userService)
{
this._UserServiceForConstructor = userService;
}
public IUserService _UserServiceForProperty { get; set; }
public ActionResult Index()
{
//使用构造函数注入的接口
string dateStr = _UserServiceForConstructor.FormatDate(DateTime.Now, false);
//使用属性函数注入的接口
string userId = _UserServiceForProperty.GetCurrentUserId();
var catService = IocService.Container.ResolveNamed<IActionService>("Cat");
string catStr = catService.SayHi();
var dogService = IocService.Container.ResolveKeyed<IActionService>("Dog");
string dogStr = dogService.SayHi();
string a = ";";
ViewBag.PageData = string.Join(a, new List<string>() { dateStr, userId, catStr, dogStr });
return View();
}
}
前端:
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title></title>
</head>
<body>
<div>
@ViewBag.PageData
</div>
</body>
</html>
运行结果:
Ending~