首页 > 编程语言 >c#MVC使用AutoFac实现IoC容器,接口多个实现的注入

c#MVC使用AutoFac实现IoC容器,接口多个实现的注入

时间:2023-08-07 11:22:51浏览次数:37  
标签:AutoFac container string Service c# builder MVC serviceName public

AutoFac能够实现自动注入    Net Core同接口多个实现依赖注入    相关资料

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";
}
}
}
运行之后我们就能看到效果了
————————————————
版权声明:本文为CSDN博主「shshdxk」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shshdxk/article/details/103927483

标签:AutoFac,container,string,Service,c#,builder,MVC,serviceName,public
From: https://www.cnblogs.com/Alex80/p/17610940.html

相关文章

  • c#格式化字符串 toString()
    1、使用ToString方法的默认格式设置publicclassAutomobile{publicstringName{get;set;}="小王";}AutomobilefirstAuto=newAutomobile();Console.WriteLine(firstAuto.ToString());2、重写ToStringpublicclassAutomobile2{publicstringNam......
  • Mitsubishi 三菱FXPLC基础 | 时钟处理指令知识分享
    谈及时钟和定时器,想来大家都不陌生,就如我,每天都要定三个闹钟才起得了床去上班,而且我敢肯定,不止我一个人。关于时钟和定时器,我在之前的文章就有分享过一二,但当时并没有讲到相关的指令,不是我不想讲,而是时机未到。然后我掐指一算,现在时机正好!在三菱FXPLC中,可以用于表示时间的有......
  • license激活
    将license对应插入电脑在电脑所用应用中找到VectorLicenseClient 点击左上角的Activate会显示ActivateLicense窗口 在ActivateKey输入激活码,点击Load   将红框处选择对应的Licensecarrier,即PC信息,选择红色打勾处,再按 Activate出现下图就表示激活成功了......
  • NETCORE - enum 枚举
    NETCORE-enum枚举                 引用:https://www.coder.work/article/969924引用:https://stackoverflow.com/questions/23794691/extension-method-to-get-the-values-of-any-enum ......
  • Mitsubishi 三菱FXPLC入门之这磨人的PLC语法(上)
    亲们,我又来分享我的PLC学习心得了,经过上一次的打脸事件后,我这次带着英语小白学ABC的心态打开了第三章的内容:编程基础。在学习之前我看到标题,心里就想着,哎呦,终于可以上手编程了,我离PLC大神就差那么临门一脚了,爽歪歪~当我打开课程后,我的天,这啥?这又是啥?@#¥%%……&&想来,我的PLC......
  • Mitsubishi 三菱FXPLC入门之这磨人的PLC语法(中)
    一、指令谈及指令,我们很容易联想到命令,所谓军令如山,在古代军队中上级发布的命令,下级必须执行,不得违抗。如果说我们是将军,那么PLC就是一个下级,我们通过不同的指令指使PLC执行各种任务,而且它不得违抗,除非它罢工了。一般一条指令是由操作码和操作数组成的,如图中的LDX0指......
  • excel 合并单元格内容数据写入
    youcanusethiscodetoopen(test.xlsx)fileandmodifyA1cellandthensaveitwithanewnameimportopenpyxlxfile=openpyxl.load_workbook('test.xlsx')sheet=xfile.get_sheet_by_name('Sheet1')sheet['A1']='hel......
  • 如何将 Microsoft Access 数据转移到 SQL Server 数据库
    在本文中,我们将为您提供一个包含屏幕截图的分步教程,介绍如何使用dborgeStudioforSQLServer 将MicrosoftAccess数据库转换为SQLServer。这个GUI工具几乎可以增强使用数据库的每个方面,包括数据库设计、SQL编码、数据库比较、模式和数据同步、有用测试数据的生成以及许多......
  • 构建跨平台的.NET Core控制台应用程序
    在本博客中,我们将介绍如何构建一个跨平台的.NETCore控制台应用程序。.NETCore是一个开源的跨平台框架,它可以在Windows、macOS和Linux等操作系统上运行。通过.NETCore,我们可以轻松地构建具有高度可移植性的应用程序。以下是步骤:步骤1:安装.NETCoreSDK首先,你需要安装.NETCoreSD......
  • 使用Entity Framework Core进行数据库操作
    当使用EntityFrameworkCore(EFCore)进行数据库操作时,你需要首先设置数据库上下文(DbContext),定义实体类(Entity),然后通过上下文来执行CRUD(创建、读取、更新和删除)操作。下面是一个简单的示例,演示如何使用EFCore进行数据库操作。安装EFCoreNuGet包:首先,你需要在项目中安装Entity......