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";
}
}
}
運行之後我們就能看到效果了