.net6 其实是自带了Ioc容器的,但是功能有限。所以今天要介绍的是引入Autofac来替代微软自带的Ioc
在引入Autofac之前,需要一个读取appsetting的工具方法,由于这个方法目前在.net5 至.net7中通用(微软ms不提供读取appsetting的方法啦,需要自己动手啦),因此将方法放在CommonCode中
读取appsetting是为了实现解耦,可以从配置文件创建实例到容器
先是NuGet包。net6 的NuGet非常多,有一些是建立项目时先安装了,也有一些是写代码的时候需要才装的,完全是按需安装的
using Microsoft.Extensions.Configuration;
namespace CommonCode.Helper
{
public class AppsettingHelper
{
private static IConfiguration _config;
private static string _basePath;
public AppsettingHelper(IConfiguration config)
{
_config = config;
_basePath = AppContext.BaseDirectory;
}
public static string Get(string key, string settingFileName = "appsettings.json")
{
string value = null;
try
{
if (string.IsNullOrWhiteSpace(key))
{
return null;
}
//引用Microsoft.Extensions.Configuration;
var Configuration = new ConfigurationBuilder()
.SetBasePath(_basePath)
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.test.json", true, reloadOnChange: true);
var config = Configuration.Build();
value = config[key];
}
catch (Exception ex)
{
value = null;
}
return value;
}
/// <summary>
/// 读取实体信息
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="session"></param>
/// <returns></returns>
public static List<T> Get<T>(params string[] session)
{
List<T> list = new List<T>();
_config.Bind(string.Join(":", session), list);
return list;
}
}
}
然后需要建立AppSetting的实体模型。仍然是放在Utility项目中
namespace NET6Demo.Utility.AppModel
{
public class Component
{
public string ServiceName { get; set; }
public string InterfaceName { get; set; }
public string InstanceScope { get; set; }
public bool InjectProperties { get; set; }
}
}
接下来我们去构造放置实例的DLL
首先在项目Interface中创建一个空接口,用来区分是否是要在容器中注册的实例
namespace NET6Demo.Interface.Dependency
{
public interface IDependency
{
}
}
我们将要创建的实例,统一放置在Service和Repository项目中。每个实例应该是按对儿出现,一个接口一个实例。
service主要提供业务逻辑,Repository主要提供viewmodel
先写一个简单的例子
1。创建Repository的基类接口,创建一个实例接口
IBaseviewmodel.cs
namespace GradeApps.AuthService.IRepository
{
public interface IBaseviewmodel
{
}
}
IUserInfo.cs
namespace GradeApps.AuthService.IRepository
{
public interface IUserInfo : IBaseviewmodel
{
public int Id { get; set; }
public string? Name { get; set; }
public string? UserId { get; set; }
public DateTime CreateAt{ get; set; }
}
}
在项目Repository中创建实现类
Baseviewmodel.cs
namespace NET6Demo.Repository
{
public abstract class Baseviewmodel
{
}
}
UserInfo.cs
using NET6Demo.Interface.Dependency;
using NET6Demo.IRepository;
namespace NET6Demo.Repository
{
public class UserInfo : Baseviewmodel, IUserInfo, IDependency
{
public int Id { get; set; }
public string? Name { get; set; }
public string? UserId { get; set; }
public DateTime CreateAt { get; set; }
}
}
然后在IService项目中创建
IBaseService.cs
namespace GradeApps.AuthService.IService
{
public interface IBaseService : Idisposable
{
}
}
IUser.cs
using NET6Demo.IRepository;
namespace NET6Demo.IService
{
public interface IUsers : IBaseService
{
IUserInfo GetUser(string userId);
}
}
Service项目,建立User.cs。这里要注意,在这里我们用到了从容器中取实例,因此要安装包
using NET6Demo.Interface.Dependency;
using NET6Demo.IRepository;
using NET6Demo.IService;
using Microsoft.Extensions.DependencyInjection;
namespace NET6Demo.Service
{
public class Users : IUsers, IDependency
{
private readonly IServiceProvider _container;
public Users(IServiceProvider container)
{
_container = container;
}
public void dispose()
{
}
public IUserInfo GetUser(string userId)
{
var user2 = _container.GetService<IUserInfo>();
user2.Name = "catcat";
user2.UserId = userId;
user2.Id = 3;
user2.CreateAt = DateTime.Now;
return user2;
}
}
}
由于我们要注册多个实例,写在program.cs中显得过于冗长,接下来我们需要一个注册实例到container的工具类,来放置这些代码
首先是NuGet包。.
在Utility项目中添加Autofac文件夹,并在其中添加AutofacModule.cs文件
using Autofac;
using CommonCode.Helper;
using NET6Demo.Interface.Dependency;
using NET6Demo.Utility.AppModel;
using System.Reflection;
using Module = Autofac.Module;
namespace NET6Demo.Utility.Autofac
{
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder container)
{
base.Load(builder);
Type baseType = typeof(IDependency);
var basePath = AppContext.BaseDirectory;
List<Component> components = AppsettingHelper.Get<Component>("Components");
foreach (var c in components)
{
var iServiceDll = $"{basePath}{c.InterfaceName}";
var ServiceDll = $"{basePath}{c.ServiceName}";
Assembly iServiceAssembly = Assembly.LoadFile(iServiceDll);
Assembly serviceAssembly = Assembly.LoadFile(ServiceDll);
container.RegisterassemblyTypes(iServiceAssembly, serviceAssembly)
.Where(b => !b.IsAbstract && baseType.IsAssignableFrom(b))
.AsImplementedInterfaces();
}
//以下代码用于注册其它实例,暂时先注释
// 用于Jwt的各种操作
// container.RegisterType<JwtSecurityTokenHandler>().InstancePerLifetimeScope();
//自己写的支持泛型存入Jwt 便于扩展
// container.RegisterType<TokenHelper>().InstancePerLifetimeScope();
//api返回值处理
// container.RegisterType<ResultHelper>().InstancePerLifetimeScope();
}
}
}
然后在program.cs中添加autofac的引用
先将AppsettingHelper注册为单例,并将config传递进去
builder.Services.Configure<IConfiguration>(config);
builder.Services.AddSingleton(new CommonCode.Helper.AppsettingHelper(config));
//在AddControllers()之前添加以上两句
builder.Services.AddControllers();
#region 添加Autofac
//替换内置的ServiceProviderFactory
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
containerBuilder.RegisterModule<AutofacModule>();
});
#endregion
在appsetting.json中添加相关设置,此时我的appsetting.json文件,长这样
{
"Logging": {
"LogLevel": {
"Default": "information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Components": [
{
"ServiceName": "NET6Demo.Repository.dll",
"InterfaceName": "NET6Demo.IRepository.dll",
"InstanceScope": "InstancePerDependency",
"InjectProperties": true
},
{
"ServiceName": "NET6Demo.Service.dll",
"InterfaceName": "NET6Demo.IService.dll",
"InstanceScope": "InstancePerDependency",
"InjectProperties": true
}
}
到这里,有一个非常重要的点:要记得将编译好的dll文件拷贝到api项目的bin文件夹下。为什么这么做?因为是这依赖倒置的核心意义,解耦。以后项目需要升级的时候,我们只要将这4个dll文件重新拷贝,就可以完成升级啦!
此时autofoac引用已经完成,可以TestController中测试一下。此时TestController.cs 长这样
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using NET6Demo.IRepository;
using NET6Demo.IService;
namespace NET6Demo_WebApi.Controllers
{
public class TestController : BaseController
{
private ILogger<TestController> _logger;
private readonly IServiceProvider _provider;
private IUserInfo _user;
public TestController(
ILogger<TestController> logger,
IServiceProvider provider,
IUserInfo user)
{
_logger = logger;
_provider = provider;
_user = user;
}
[AllowAnonymous]
[HttpGet("GetTest")]
public async Task<IActionResult> GetTestResult(string userId)
{
Console.WriteLine("测试一下输出日志");
_logger.Loginformation("日志输出了");
_user = _provider.GetService<IUsers>().GetUser(userId);
return Ok(_user);
}
}
}
然后运行起来,在swagger中测试GetTestAPI
已经可以得到了想要的结果
注意:有报错,一般都是因为缺少引用,或者安装Nuget包,或者按vs2022的提示进行引用
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。