AutoFac能够实现自动注入
AutoFac下载的引入
使用nuget包管理引入AutoFac
添加打勾的3个,AutoFac容器,AutoFac的apiController支持,AutoFac的mvc支持
在Global.asax中注册AutoFac
protected void Application_Start()
{
Register(typeof(IService).Assembly);
}
protected void Register(params Assembly[] assemblys)
{
var builder = new ContainerBuilder();
// 注册type接口的程序集中包含Service的接口
builder.RegisterAssemblyTypes(assemblys).AsImplementedInterfaces();
// 注册主项目的Controllers
builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
// 注册主项目的ApiControllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
builder.RegisterWebApiModelBinderProvider();
// 获取注入容器
var container = builder.Build();
// 设置MVC的注入解析程序
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// 设置Api的注入解析程序
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
其中IService是需要需要注入项目接口放置的程序集中的一个类,不需要实现
namespace Service
{
public interface IService
{
}
}
使用AutoFac
在IService所在程序集添加一个接口类,一个实现类
namespace Service.Api
{
public interface ITranslationService
{
string Lang();
}
}
namespace Service.Impl
{
public class TranslationServiceImpl : ITranslationService
{
public string Lang()
{
System.Diagnostics.Debug.WriteLine("调用成功");
}
}
}
在Controller中注入
namespace Aca.Certain.Web.Controllers
{
public class PatientController : Controller
{
private readonly ITranslationService _translationService;
public PatientController(ITranslationService translationService)
{
this._translationService = translationService;
}
public string text()
{
_translationService.Lang();
return "success";
}
}
}
访问controller就能看到效果了
上面就是AutoFac的简单使用
但是,写过项目的人就会发现,光光上面那种使用方法,正真使用起来很鸡肋,经常有一个接口多个实现的情况出现,像上面那样使用就不行了
那么我们就来对程序进行一些修改,做到能想spring一样,根据名称获取要注入的类,并且不是所有的接口实现都需要依赖注入的,需要排除一些我们不需要的
定义Service注解
要有名称,首先要给接口实现一个名字,我们可以使用一个Attribute
namespace Common.Autofac
{
public class ServiceAttribute : Attribute
{
private readonly string _name = "";
public ServiceAttribute()
{
var a = this;
}
public ServiceAttribute(string name)
{
this._name = name;
}
public string Name
{
get { return _name; }
}
}
}
在Serveice是实现加上注解
namespace Service.Api
{
public interface ITranslationService
{
string Lang();
}
}
namespace Service.Impl
{
[Service("service1")]
public class TranslationServiceImpl : ITranslationService
{
public string Lang()
{
System.Diagnostics.Debug.WriteLine("调用1成功");
}
}
}
namespace Service.Impl
{
[Service("service2")]
public class TranslationServiceImpl : ITranslationService
{
public string Lang()
{
System.Diagnostics.Debug.WriteLine("调用2成功");
}
}
}
写一个根据名称获取Service的方法
namespace Aca.Certain.Common.Autofac
{
/// <summary>
/// 基于Autofac的服务定位器
/// </summary>
public class ServiceLocator
{
private static Dictionary<string, object> _serviceDict = new Dictionary<string, object>();
private static IContainer _container;
/// <summary>
/// 设置Ico容器
/// </summary>
/// <param name="container"></param>
public static void SetContainer(IContainer container)
{
_container = container;
}
/// <summary>
/// 获取容器对象
/// </summary>
/// <returns></returns>
public static IContainer GetContainer()
{
return _container;
}
public static TService GetService<TService>()
{
return _container.Resolve<TService>();
}
/// <summary>
/// 根据serviceName获取Service,不区分大小写
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <param name="serviceName"></param>
/// <returns></returns>
public static TService GetServiceByName<TService>(string serviceName)
{
serviceName = serviceName.ToLower();
if (_serviceDict.ContainsKey(serviceName))
{
return (TService)_serviceDict[serviceName];
}
lock (serviceName)
{
if (_serviceDict.ContainsKey(serviceName))
{
return (TService)_serviceDict[serviceName];
}
var list = AutofacDependencyResolver.Current.GetServices(typeof(TService));
if (list.Count() == 0)
{
throw new NullReferenceException(); ;
}
foreach (var item in list)
{
Type type = item.GetType();
Attribute sa = type.GetCustomAttribute(typeof(ServiceAttribute));
if (sa != null)
{
if (((ServiceAttribute)sa).Name.ToLower() == serviceName.ToLower())
{
_serviceDict.Add(serviceName, item);
return (TService)item;
}
}
}
_serviceDict.Add(serviceName, list.ElementAt(0));
return (TService)list.ElementAt(0);
}
}
}
}
这个方法是根据name查找Service,没找到时,返回第一个
修改Global.asax中Register方法
protected void Register(params Assembly[] assemblys)
{
var builder = new ContainerBuilder();
// 注册type接口的程序集中包含Service的接口
builder.RegisterAssemblyTypes(assemblys).Where(t =>
t.GetCustomAttribute(typeof(ServiceAttribute)) != null
).AsImplementedInterfaces();
// 注册主项目的Controllers
builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
// 注册主项目的ApiControllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
builder.RegisterWebApiModelBinderProvider();
// 获取注入容器
var container = builder.Build();
//设置服务容器
ServiceLocator.SetContainer(container);
// 设置MVC的注入解析程序
DependencyResolver.SetResolver(new AutofacDependencyResolver(ServiceLocator.GetContainer()));
// 设置Api的注入解析程序
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
修改Controller
namespace Aca.Certain.Web.Controllers
{
public class PatientController : Controller
{
private readonly ITranslationService _service1;
private readonly ITranslationService _service2;
public PatientController()
{
this._service1 = ServiceLocator.GetServiceByName<ITranslationService>("service1");
this._service2 = ServiceLocator.GetServiceByName<ITranslationService>("service2");
}
public string text()
{
_service1.Lang();
_service2.Lang();
return "success";
}
}
}
运行之后我们就能看到效果了