AutoRegistDependency 1.0.37

There is a newer version of this package available.
See the version list below for details.
dotnet add package AutoRegistDependency --version 1.0.37                
NuGet\Install-Package AutoRegistDependency -Version 1.0.37                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AutoRegistDependency" Version="1.0.37" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add AutoRegistDependency --version 1.0.37                
#r "nuget: AutoRegistDependency, 1.0.37"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install AutoRegistDependency as a Cake Addin
#addin nuget:?package=AutoRegistDependency&version=1.0.37

// Install AutoRegistDependency as a Cake Tool
#tool nuget:?package=AutoRegistDependency&version=1.0.37                

AutoRegistDependency

介绍

AutoFac二次封装,实现根据特性自动注入功能

使用说明

nuget 搜索 AutoRegistDependency 进行安装

  1. 注册服务 program.cs文件中 (.net6以上)

builder.Host.ConfigureContainer<ContainerBuilder>((hostBuilderContext, containerBuilder) =>
{
        //以下两种方式都可以
        containerBuilder.RegisterModule(new Register(hostBuilderContext));
	new Register(hostBuilderContext).RegisterType(containerBuilder);
});
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
 **如果控制器需要使用autofac原生属性注入,需要使autofac接管controller,需添加以下代码** 
builder.Services.AddControllers().AddControllersAsServices();//控制器生成作为服务
builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());
WebApplication? app = builder.Build();
//这句为启用quartz注册的任务,没有这句代码定时任务不启动!!
app.Services.QuartzRegist();

.net core 3.x program.cs文件中

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                   .ConfigureContainer<ContainerBuilder>((hostBuilderContext, containerBuilder)=>
                {
                    new Register(hostBuilderContext).RegisterType(containerBuilder);
                    //启用Quartz module!!
                    containerBuilder.RegisterModule(new QuartzAutofacFactoryModule());
                })
                  .UseServiceProviderFactory(new AutofacServiceProviderFactory());

startup.cs 文件中

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.ApplicationServices.QuartzRegist();
}

.net core 2.x (暂时先请用1.0.9之前的版本 ) startup文件中,改写ConfigureServices方法

 public IServiceProvider ConfigureServices(IServiceCollection services)

 {
            
    var builder = new ContainerBuilder();//实例化 AutoFac  容器
    builder.Populate(services);//管道寄居
    new Register()
        //.SetDefaultLifeTime() //设置所有实例的默认生命周期,默认scope
    .RegisterType(builder);
    ApplicationContainer = builder.Build();
    return new AutofacServiceProvider(ApplicationContainer);//将autofac反馈到管道中

 }

特别说明:此组件默认读取系统的IConfignature服务获取配置文件数据,默认支持nacos读取json文件(如果nacos注册成功的话)

  1. 特性说明

ComponentAttribute 只能标记在类上,代表此类型需要被自动注入

/// constructor
/// </summary>
/// <param name="lifetime">生命周期</param>
/// <param name="autoActivate">是否自动激活实例</param>
/// <param name="interceptorType">拦截器代理类型</param>
/// <param name="name">服务名(默认类名简称)</param>
/// <param name="key">服务key</param>
/// <param name="registType">注册类型(注册自己本身还是作为接口实现类)</param>
/// <param name="propertyInjectType">autofac属性注入方式,是否通过特性标记需要注入的属性</param>
public ComponentAttribute(LifeTimeType lifetime = LifeTimeType.Default, bool autoActivate = false,
string name = "",object key=null,RegistType registType= RegistType.Default,
PropertyInjectType propertyInjectType = PropertyInjectType.Default)
{
    Lifetime = lifetime;
    AutoActivate = autoActivate;
    Name = name;
    PropertyInjectType = propertyInjectType;
    Key = key;
    RegistType= registType;
}

ConfigurationPropertiesAttribute 只能标记在类上,代表此类型是通过配置文件读取并进行实例绑定

/// <summary>
/// constructor
/// </summary>
public ConfigurationPropertiesAttribute(string path)
{
    Path = path;//path为使用IConfiguration读取数据的key,和.net core原生读取规则一致
}

ConfigurationAttribute 只能标记在类上,代表此类被容器单例管理,通常配合bean使用

public sealed class ConfigurationAttribute:Attribute
{
}

注意 以上三种特性在同一个类中只能拥有一个,也就是说一个类只能作为一种服务类型注册到容器中!

BeanAttribute 只能标记在方法上,代表此方法返回的实例需要被管理 (此方法的类上未标记ConfigurationAttribute无效!!)

/// <summary>
/// constructor
/// </summary>
public BeanAttribute(string name = "",object key=null,LifeTimeType lifeTimeType = LifeTimeType.Default)
{
    Name = name;
    Key= key;
    LifeTimeType = lifeTimeType;
}

AutowiredAttribute 可以标记在属性、字段上以及方法上 代表此属性(字段)将注入到实例中

/// <summary>
/// constructor
/// </summary>
/// <param name="name">需要获取的服务名(根据参数的类型和name去取)</param>
public AutowiredAttribute(string name = "")
{
   Name = name;
}

ValueAttribute 可标记在属性,字段和参数上。代表被标记的对象需要从配置文件中自动读取数据

//path为读取配置文件的字符串,和使用IConfiguration原生读取规则相同。
public ValueAttribute(string path)
{
   Path = path;
}

OrderAttribute 标记在类上,代表服务注册的顺序 越小越先注册

/// <summary>
/// constructor
/// </summary>
public OrderAttribute(int order)
{
   this.Order = order;
}

RegistAsAttribute 标记在类上,代表此服务以何种类型注册(如果不是注册类型的父类或者注册类型所实现的接口,在注册初始化时将会报错)

/// <summary>
/// constructor
/// </summary>
public RegistAsAttribute(params Type[] types)
{
    Types = types;
}

ConditionalAttribute 标记在类上或者方法上(支持多个特性打在同一目标),代表注册此服务是有条件的,conditionTypes为实现接口ICondition的实现类。如果hostBuilderContext为空的话,不会执行conditional特性所指定的类

public ConditionalAttribute(params Type[] conditionTypes)
{
    ConditionTypes = conditionTypes;
}

public interface ICondition
{
    bool Matches(HostBuilderContext hostBuilderContext, IComponentRegistryBuilder componentRegistry, object attributeMeta);
    参数说明:
    hostBuilderContext:包含程序整体的上下文信息,包括IHostEnvironment,IConfiguration等。
    componentRegistry:注册上下文
    attributeMeta:标记特性的原数据,Component为Type,Bean为MethodInfo
}

ConditionalOnPropertyAttribute 标记在类上或者方法上(支持多个特性打在同一目标),代表此服务的注册依赖于读取配置文件的值

/// <summary>
/// ctor
/// </summary>
/// <param name="name">配置文件名</param>
/// <param name="havingValue">配置文件值</param>
/// <param name="prefix">前缀</param>
public ConditionalOnPropertyAttribute(string name,string havingValue,string prefix="")
{
    //例如根据配置文件Logging:LogLevel:Default的值来进行注册。
    //Prefix="Logging:LogLevel" name="Default" 或者
    //name="Logging:LogLevel:Default"
    Prefix= prefix;
    Name= name;
    HavingValue= havingValue;//配置文件写的值 如果匹配就代表注册
}

JobAttribute 仅能标记在类上,代表此类为Quartz的任务类(此类必须实现Quartz的Ijob接口,否则会报错!)

/// <summary>
/// ctor
/// </summary>
/// <param name="cron">cron表达式</param>
/// <param name="priority">执行优先级 0-5</param>
public JobAttribute(string cron,int priority = 0) 
{
    Cron = cron;
    Priority = priority;
}	
  1. 动态代理注册方法 继承抽象类 AbstractInterceptor 实现抽象类的抽象方法(非泛型类的代理方法一定要是virtual,泛型类无法代理,只能代理泛型接口)
public abstract class AbstractInterceptor : IInterceptor, IAsyncInterceptor
{
  protected readonly IEnumerable<Assembly> dlls;//为实例化Register时所扫描的程序集
  public AbstractInterceptor(IEnumerable<Assembly> dlls)
  {
     this.dlls = dlls;
  }
  public abstract IEnumerable<Type> GetInterceptorTypes();//此方法返回需要被代理的所有类型
  public abstract void Intercept(IInvocation invocation);//(ps:最新版此方法使用了固定实现,不用写了!)固定写法 this.ToInterceptor().Intercept(invocation);
  public abstract void InterceptAsynchronous(IInvocation invocation);//Task返回类型的拦截方法
  public abstract void InterceptAsynchronous<TResult>(IInvocation invocation);//Task<TResult>返回类型的拦截方法
  public abstract void InterceptSynchronous(IInvocation invocation);//同步方法的拦截
}

4.事件总线功能 在需要使用事件总线的代码处注入EventBus或IEventBus:

[ApiController]
[Component]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private readonly LogModel logModel;
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;
		
    [Autowired]
    private IEventBus eventPublisher;

    public WeatherForecastController(LogModel logModel,ILogger<WeatherForecastController> logger)
    {
	_logger = logger;
	this.logModel = logModel;
    }

	[HttpGet(Name = "GetWeatherForecast")]
	public IEnumerable<WeatherForecast> Get()
	{
	    List<int> list=eventPublisher.PublishAsync<LogModel, int>(testValue).GetAwaiter().GetResult();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
	    {
		Date = DateTime.Now.AddDays(index),
		TemperatureC = Random.Shared.Next(-20, 55),
		Summary = Summaries[Random.Shared.Next(Summaries.Length)]
		})
		.ToArray();
		}
	}

在需要消费事件的代码处实现接口 IEventAsyncHandler<T,TResult> 需注意:EventBus发布的eventData和IEventAsyncHandler接口的泛型T完全匹配时,才能触发

[Component]
public class WorkListener: IEventAsyncHandler<LogModel, int>
{
    public async Task<int> Handle(LogModel eventData)
    {
        await Task.Run(() =>
	{
	    Console.WriteLine("123");
	    Task.Delay(500);
	}) ;
        return 0;
    }
}
		

IEventBus调用方法对应触发的接口如下:

public interface IEventBus
{
    /// <summary>
    /// 同步发布消息
    /// </summary>
    /// <typeparam name="T">eventData类型</typeparam>
    /// <param name="eventData">消息数据</param>
    void Publish<T>(T eventData);//ps:此方法触发实现了IEventHandler<T>的类,eventData类型和接口泛型必须相同,且消费者必须受到Autofac的管理!!
    /// <summary>
    /// 异步发布消息
    /// </summary>
    /// <typeparam name="T">eventData类型</typeparam>
    /// <param name="eventData">消息数据</param>
    /// <returns></returns>
    Task PublishAsync<T>(T eventData);//ps:此方法触发实现了IEventAsyncHandler<T>的类,eventData类型和接口泛型必须相同,且消费者必须受到Autofac的管理!!
    /// <summary>
    /// 发布消息(有返回值)
    /// </summary>
    /// <typeparam name="T">eventData类型</typeparam>
    /// <typeparam name="TResult">返回结果类</typeparam>
    /// <param name="eventData">消息数据</param>
    /// <returns></returns>
    List<TResult> Publish<T,TResult>(T eventData);//ps:此方法触发实现了IEventHandler<T,TResult>的类,eventData类型和返回值和接口泛型必须相同,且消费者必须受到Autofac的管理!!
    /// <summary>
    /// 异步发布消息(有返回值)
    /// </summary>
    /// <typeparam name="T">eventData类型</typeparam>
    /// <typeparam name="TResult">返回结果类</typeparam>
    /// <param name="eventData">消息数据</param>
    /// <returns></returns>
    Task<List<TResult>> PublishAsync<T,TResult>(T eventData);//ps:此方法触发实现了IEventAsyncHandler<T,TResult>的类,eventData类型和返回值和接口泛型必须相同,且消费者必须受到Autofac的管理!!
}

5.IBeanPostProcessor bean增强器。如果需要对注册的实例进行增强,可以实现IBeanPostProcessor,并注册到Autofac中( 注意:如果实现了IBeanPostProcessor 在注册时仅将其作为IBeanPostProcessor服务注册,不会注册自身及其他实现的接口!! )

/// <summary>
/// bean增强器
/// </summary>
public interface IBeanPostProcessor
{
    /// <summary>
    /// 构造函数构造对象成功之后对bean进行增强
    /// </summary>
    /// <param name="bean">bean实例</param>
    /// <returns>增强后的bean实例</returns>
    object PostProcessBeforeInitialization(object bean);
    /// <summary>
    /// 字段、方法、属性注入等成功之后对bean进行增强
    /// </summary>
    /// <param name="bean">bean实例</param>
    /// <returns>增强后的bean实例</returns>
    object PostProcessAfterInitialization(object bean);
}

6.聚合服务。如果需要将多个服务聚合到某一个接口组成满足业务逻辑,可以新建一个接口 如下:

[AggregateService]//聚合服务特性
public interface IMyAggregateService
{
    [Autowired(name: "Test1")]
    ITest test1();//支持使用Autowied特性筛选方法返回值
    [Autowired(name: "Test")]
    ITest test { get; }//支持使用Autowied特性筛选属性
}

注意:聚合服务不会被任何其他的代理类代理,同时也不受到IBeanPostProcessor的增强!!聚合服务定义接口一定要是同步方法,异步方法暂不支持!!

7.简单代码示例 新建web项目 新建接口和实现

public interface ITest
{
   string Say();
}
 **[Component(name:"Test")]** 
public class Test : ITest
{
   public Test() { }
   public string Say()
   {
    return nameof(Test);
   }
}

 **[Component(key: "Test1")]** 
public class Test1 : ITest
{
  public virtual string Say()
  {
    return nameof(Test1);
  }
}
//新建配置文件自动绑定实体
[ConfigurationPropertiesAttribute(path: "Logging:LogLevel")]
public class LogModel
{
   public string Default { get; set; }
}

bean类型注册
 **[Configuration]** 
public class ConfigurationTest
{
**[Bean]** 
public LogModel GetBeanObject([ComponentFilter(name: "Test")] ITest test)
{
    test.Say();
    return new LogModel()
    {
	Default = "12345"
    };
}

//拦截器
 **[Component]** 
public class TestInterceptor : AbstractInterceptor
{
   public TestInterceptor(IEnumerable<Assembly> dlls) : base(dlls)
   {
   }

   public override IEnumerable<Type> GetInterceptorTypes()
   {
       // this.dlls 为程序运行时所扫描到的所有程序集,批量拦截操作可以通过这个变量进行筛选返回相应的Types!!如下:
       //return this.dlls.Where(t => t.GetName().Name.StartsWith("Adks.WxMini.Repository") || t.GetName().Name.StartsWith("Adks.WxMini.Services")).SelectMany(t => t.GetTypes().Where(a => a.Name.EndsWith("Repository") || a.Name.EndsWith("Services")));

       //从基类继承的dll变量是扫描到的所有程序集,可以通过程序集获取对应的被代理类型 这里只是个示例
       return new Type[] { typeof(Test),typeof(Test1) };
   }
    //最新版已经在基类加入了默认实现,不再需要写一次了
    //public override void Intercept(IInvocation invocation)
    //{
	//this.ToInterceptor().Intercept(invocation);
    //}

    public override void InterceptAsynchronous(IInvocation invocation)
    {
	Console.WriteLine($"before:{nameof(InterceptAsynchronous)}");
	invocation.Proceed();//执行被拦截的返回值为Task的方法
	Console.WriteLine($"after:{nameof(InterceptAsynchronous)}");
    }

    public override void InterceptAsynchronous<TResult>(IInvocation invocation)
    {
	Console.WriteLine($"before:{nameof(InterceptAsynchronous)}");
	invocation.Proceed();
	Console.WriteLine($"after:{nameof(InterceptAsynchronous)}");
    }

    public override void InterceptSynchronous(IInvocation invocation)
    {
	Console.WriteLine($"before:{nameof(InterceptSynchronous)}");
	invocation.Proceed();
	Console.WriteLine($"after:{nameof(InterceptSynchronous)}");
     }
}
//Quartz任务注册(请注意,如果Job类型的服务需要使用动态代理,那么必须将Execute方法声明为virtual,否则无法实现代理)

[Job(cron: "0/5 * * * * ? ")]
public class TestJob : IJob
{
    //所有的注入方式都支持
    //[Value("Logging:LogLevel")]
    private LogModel testValue;
    public TestJob(LogModel testValue)
    {
        this.testValue = testValue;
    }

    public Task Execute(IJobExecutionContext context)
    {
	return Task.Run(() =>
	{
	    Console.WriteLine(testValue.Default);
	});
    }
}





//注入调用
[ApiController]
 **[Component]** 
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private readonly LogModel logModel;
    private static readonly string[] Summaries = new[]
    {
	"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;
    [Autowired(key: "Test1")]
    private Test1 test1;//属性注入,指定服务key名
    private ITest test;
    [Value("Logging:LogLevel")]
    private LogModel testValue;//配置文件注入
    [Autowired]
    private IGenercTest<LogModel> genercTest;
    [Autowired]
    private void GetTest([ComponentFilter(name: "Test")] ITest test)//方法注入,支持参数特性筛选指定服务
    {
	this.test = test;
    }

    public WeatherForecastController(LogModel logModel,ILogger<WeatherForecastController> logger)
    {
	_logger = logger;
	//this.test= test;
	this.logModel = logModel;
	//this.genercTest = genercTest;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
	Console.WriteLine($"test:{test1.Say()}");
	Console.WriteLine($"genercTest:{genercTest.Say()}");
	return Enumerable.Range(1, 5).Select(index => new WeatherForecast
	{
		Date = DateTime.Now.AddDays(index),
		TemperatureC = Random.Shared.Next(-20, 55),
		Summary = Summaries[Random.Shared.Next(Summaries.Length)]
	})
	.ToArray();
}

所有服务注册时必须加入响应的特性,否则无法注入成功(包括控制器)

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.55 109 9/6/2024
1.0.54 132 6/5/2024
1.0.53 109 6/5/2024
1.0.52 99 5/21/2024
1.0.50 154 4/24/2024
1.0.49 115 4/23/2024
1.0.48 125 2/28/2024
1.0.47 140 1/23/2024
1.0.46 194 12/5/2023
1.0.45 215 9/8/2023
1.0.44 187 8/23/2023
1.0.43 151 8/10/2023
1.0.42 155 6/26/2023
1.0.41 151 5/23/2023
1.0.40 196 4/18/2023
1.0.39 197 4/14/2023
1.0.38 186 4/11/2023
1.0.37 201 4/11/2023
1.0.36 217 4/3/2023
1.0.35 240 3/16/2023
1.0.34 270 3/6/2023
1.0.32 243 3/3/2023
1.0.31 256 3/2/2023
1.0.30 253 3/2/2023
1.0.29 252 3/1/2023
1.0.28 273 2/25/2023
1.0.27 266 2/22/2023
1.0.26 259 2/22/2023
1.0.25 253 2/21/2023
1.0.24 257 2/20/2023
1.0.23 248 2/17/2023
1.0.22 319 2/15/2023
1.0.21 283 2/13/2023
1.0.20 271 2/9/2023
1.0.19 274 2/9/2023
1.0.18 282 2/7/2023
1.0.17 264 2/7/2023
1.0.16 258 2/7/2023
1.0.15 277 2/4/2023
1.0.14 287 2/2/2023
1.0.13 309 1/31/2023
1.0.12 296 1/31/2023
1.0.11 283 1/31/2023
1.0.10 311 1/30/2023
1.0.9 306 1/30/2023
1.0.8 302 1/30/2023
1.0.5 296 1/28/2023
1.0.4 321 1/28/2023
1.0.3 316 1/23/2023
1.0.2 317 1/21/2023
1.0.1 311 1/17/2023
1.0.0 318 1/17/2023

动态代理添加基类的默认实现。