AutoRegistDependency 1.0.53

There is a newer version of this package available.
See the version list below for details.
dotnet add package AutoRegistDependency --version 1.0.53                
NuGet\Install-Package AutoRegistDependency -Version 1.0.53                
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.53" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add AutoRegistDependency --version 1.0.53                
#r "nuget: AutoRegistDependency, 1.0.53"                
#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.53

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

AutoRegistDependency

介绍

AutoFac二次封装,实现根据特性自动注入功能。 Based on AutoFac development, achieve automatic injection function according to characteristics.

使用说明

nuget 搜索 AutoRegistDependency 进行安装

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

builder.Host.ConfigureContainer<ContainerBuilder>((hostBuilderContext, containerBuilder) =>
{
        //以下两种方式都可以 Both of the following methods are possible
        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 只能标记在类上,代表此类型需要被自动注入

/// <summary>
/// 组件注入特性。可以标记在类上。Component、Confignature、Job以及ConfigurationProperties特性在同一个类上只能有一个。
/// Component injection attribute. Can be marked on a class. 
/// The Component, Configure,Job,ConfigurationProperties attributes can only have one on the same class.
/// </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>
/// 配置文件实体模型特性。标记在类上。将会把配置文件内读取到的json文件转为对应类的实例。读取的规则和.net core原生读取规则相同。
/// Component、Confignature、Job以及ConfigurationProperties特性在同一个类上只能有一个。
/// Configure the physical model properties of the file. Mark on class. 
/// The JSON file read from the configuration file will be converted into an instance of the corresponding class.
/// The reading rules are the same as the native reading rules for. net core.
/// The Component, Configure, Job, and ConfigurationProperties attributes can only have one on the same class.
/// </summary>
public ConfigurationPropertiesAttribute(string path)
{
    Path = path;//path为使用IConfiguration读取数据的key,和.net core原生读取规则一致
}

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

/// <summary>
/// 标记此特性代表容器管理此类型的一个单例,通常作为配置类管理需要注册的服务需要和BeanAttribte配合使用。Component、Confignature以及Job特性在同一个类上只能有一个。
/// Marking this Attribute represents a singleton of container management for this type, typically used in conjunction with BeanAttribute as a configuration class to manage registered services. 
/// The Component, Configure, and Job attributes can only have one on the same class.
/// </summary>
public sealed class ConfigurationAttribute:Attribute
{
}

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

/// <summary>
/// 定时任务注册特性。仅能标记在类上。
/// Component、Confignature、Job以及ConfigurationProperties特性在同一个类上只能有一个。
/// 注册之后还需调用RegisterExtension.QuartzRegist方法才能成功启动任务。
/// 如果定时任务类需要使用动态代理,一定要将Execute方法声明为virtual!因为定时任务启动时调用的是IJob的实现类而非IJob接口!
/// Timer task registration feature. Can only be marked on a class.
/// The Component, Configure, Job, and ConfigurationProperties attributes can only have one on the same class.
/// After registration, the RegisterExtension.QuartzRegister method needs to be called to successfully start the task.
/// If the scheduled task class requires the use of dynamic proxies, be sure to declare the Execute method as virtual! 
/// Because the implementation class of IJob is called when the scheduled task starts, not the IJob interface!
/// <param name="cron">cron表达式</param>
/// <param name="priority">执行优先级 0-5</param>
public JobAttribute(string cron,int priority = 0) 
{
    Cron = cron;
    Priority = priority;
}	

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

/// <summary>
/// 方法上进行标记。将返回的实例注册到容器中(返回值为Task或者void的方法不会注册)。Bean所在的类上无ConfigurationAttribute特性将不会注册。
/// 如果注册的方法是个泛型方法,那么泛型方法的返回值也必须是个泛型,且返回值的泛型的数量和顺序必须和方法一致。
/// 例如:public BeanTest1 &lt;T&gt; TestBean1 &lt;T&gt;() where T: class=>new BeanTest1 &lt;T&gt;();BeanTest1 为泛型类,在注册时会当成开放泛型进行注册。否则泛型方法返回的实例不会被注册。
/// Mark the method. Register the returned instance into the container (methods with a return value of Task or void will not be registered). 
/// If there is no ConfigurationAttribute attribute on the class where the bean is located, it will not be registered.
/// If the registered method is a generic method, the return value of the generic method must also be a generic, and the number and order of generics for the return value must be consistent with the method.
/// For example: public BeanTest1 &lt;T&gt; TestBean1 &lt;T&gt;() where T: class=>new BeanTest1 &lt;T&gt;(); BeanTest1 is a generic class that will be registered as an open generic during registration. 
/// Otherwise, the instance returned by the generic method will not be registered.
/// </summary>
public BeanAttribute(string name = "",object key=null,LifeTimeType lifeTimeType = LifeTimeType.Default)
{
    Name = name;
    Key= key;
    LifeTimeType = lifeTimeType;
}

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

/// <summary>
/// 自动装配特性,可以标记在属性、字段以及方法上。可以根据特性的属性筛选不同的实现类。
/// Automatic assembly features can be marked on attributes, fields, and methods.
/// You can filter different implementation classes based on the properties of the feature.
/// </summary>
/// <param name="name">需要获取的服务名(根据参数的类型和name去取)</param>
public AutowiredAttribute(string name = "")
{
   Name = name;
}

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

/// <summary>
/// 配置文件值读取特性。可标记在类、属性、字段以及构造函数参数上。读取配置文件对应key的值,读取规则和原生.net core一致。
/// Configuration file value reading feature. Can be marked on classes, properties, fields, and constructor parameters. 
/// Read the value of the key corresponding to the configuration file, and the reading rules are consistent with the native. net core.
/// </summary>
/// <param name="path">配置文件key</param>
public ValueAttribute(string path,Type valueHandler=null)
{
   Path = path;
}
///如果需要对注入的配置文件值进行二次处理(例如配置文件加密解密),可以在特性value上加入一个实现了接口IValueHandler的实现类
///在执行ValueHandler时会首先查找已经在容器内注册的ValueHandler实现类(容器内注册的handler可以使用任何其他依赖注入的组件),如果未找到,会通过反射new一个出来。
/// <summary>
/// 使用value获取配置文件值后对value继续进行处理的方法
/// </summary>
public interface IValueHandler
{
    /// <summary>
    /// 执行转换方法
    /// </summary>
    /// <param name="value">通过配置文件获取的值</param>
    /// <returns></returns>
    object Execute(object value);
}

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

/// <summary>
/// 组件注册顺序特性。值越小越先注册(对bean无效)
/// Component registration order feature. Register first with smaller values (invalid for bean)
/// </summary>
public OrderAttribute(int order)
{
   this.Order = order;
}

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

/// <summary>
/// 注册目标类型特性,可标记在类上和方法上。目标类型必须为此类实现的接口或父类。
/// Register target type attributes that can be marked on classes and methods.
/// The target type must be an interface or parent class implemented by this class.
public RegistAsAttribute(params Type[] types)
{
    Types = types;
}

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

/// <summary>
/// 条件注册特性。可以标记在类以及方法上。根据不同的条件实现类判断是否注册标记的服务。
/// Conditional registration attribute. Can be marked on classes and methods. 
/// Implement classes based on different conditions to determine whether to register marked services.
/// </summary>
/// <param name="conditionTypes">必须为实现了ICondition接口的类。Must be a class that implements the ICondition interface</param>
public ConditionalAttribute(params Type[] conditionTypes)
{
    ConditionTypes = conditionTypes;
}
/// <summary>
/// 注册条件判断接口。
/// Registration condition judgment interface
/// </summary>
public interface ICondition
{
    bool Matches(HostBuilderContext hostBuilderContext, IComponentRegistryBuilder componentRegistry, object attributeMeta);
    参数说明:
    hostBuilderContext:包含程序整体的上下文信息,包括IHostEnvironment,IConfiguration等。
    componentRegistry:注册上下文
    attributeMeta:标记特性的原数据,Component为Type,Bean为MethodInfo
}

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

/// <summary>
/// 根据配置文件项决定组件是否注册特性。可以标记在方法以及类上。
/// Determine whether the component registers features based on the configuration file items. Can be marked on methods and classes.
/// </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;//配置文件写的值 如果匹配就代表注册
}

ConditionalOnBeanAttribute 当容器内存在指定的组件时,才会注册此组件 This component is only registered when the specified component exists within the container.

ConditionalOnMissBeanAttribute 当容器内缺少指定组件,才注册此组件 Register this component only when the specified component is missing from the container

/// <summary>
/// 组件依赖特性
/// 使用此组件可标记当前组件初始化之前需要的其他组件并初始化并缓存
/// 。同时使用构造函数注入组件时,会优先使用和初始化类型相同的缓存类型。如果构造函数参数标记了[ComponentFilterAttribute]特性,不会使用此参数的缓存实例。
/// Component dependency characteristics.
/// Use this component to mark other components required before initializing the current component and initialize and cache them. When using constructors to inject components simultaneously, cache types with the same initialization type will be prioritized.
/// If the constructor parameter is marked with the [ComponentFilterAttribute], the cached instance of this parameter will not be used.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
public sealed class DependsOnAttribute : AbstractTyped
{
    public Type CompnentType { get; set; }
    public DependsOnAttribute(Type compnentType,string name="")
    {
        CompnentType = compnentType;
        if (string.IsNullOrWhiteSpace(name))
        {
            Name = CompnentType.Name;
        }
    }
    public DependsOnAttribute(Type compnentType,object key)
    {
        Key = key;
        CompnentType = compnentType;
    }
}

DependsOnAttribute特性,标记此组件实例化之前需要初始化其他的组件并缓存。在使用构造函数的方式注入依赖时,优先使用缓存内的实例。如果标记了ComponentFilterAttribute 特性,指定的参数将不会使用缓存内实例。如果使用的是属性或者字段注入,此方式将不起作用,只能起到优先初始化其他参数的作用。

  1. 动态代理注册方法 继承抽象类 AbstractInterceptor 实现抽象类的抽象方法(非泛型类的代理方法一定要是virtual,泛型类无法代理,只能代理泛型接口)
/// <summary>
/// 代理抽象类,动态代理需继承此类并重写他的方法。
/// Proxy abstract class.Dynamic proxy needs to inherit this class and override its methods
/// </summary>
public abstract class AbstractInterceptor : IInterceptor, IAsyncInterceptor
{
    /// <summary>
    /// 初始化Register扫描到的所有程序集。
    /// Initialize all assemblies scanned by Register class.
    /// </summary>
    protected readonly IEnumerable<Assembly> dlls;
    /// <summary>
    /// ctor
    /// </summary>
    /// <param name="dlls"></param>
    public AbstractInterceptor(IEnumerable<Assembly> dlls)
    {
        this.dlls = dlls;
    }
    /// <summary>
    /// 此方法获取此拦截器所有需要代理的类。
    /// This method obtains all classes that require proxies for this interceptor.
    /// </summary>
    /// <returns></returns>
    public abstract IEnumerable<Type> GetInterceptorTypes();
    /// <summary>
    /// 将同步代理转为异步代理。如有特殊需求可以重写此方法。
    /// Convert synchronous proxy to asynchronous proxy.Override if needed.
    /// </summary>
    /// <param name="invocation">代理方法的调用。Encapsulates an invocation of a proxied method.</param>
    public virtual void Intercept(IInvocation invocation)
    {
        this.ToInterceptor().Intercept(invocation);
    }
    /// <summary>
    /// 返回值为Task的异步方法都会走这个方法。
    /// Asynchronous methods with a return value of Task will use this method
    /// </summary>
    /// <param name="invocation">代理方法的调用。Encapsulates an invocation of a proxied method.</param>
    public abstract void InterceptAsynchronous(IInvocation invocation);
    /// <summary>
    /// 返回值为泛型Task的异步方法都会走这个方法。
    /// Asynchronous methods that return a generic Task will use this method.
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    /// <param name="invocation">代理方法的调用。Encapsulates an invocation of a proxied method.</param>
    public abstract void InterceptAsynchronous<TResult>(IInvocation invocation);
    /// <summary>
    /// 同步方法都会走这里。
    /// All synchronization methods will will use this method.
    /// </summary>
    /// <param name="invocation">代理方法的调用。Encapsulates an invocation of a proxied method.</param>
    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增强器。可对组件初始化前后对组件功能进行增强。
/// Bean enhancer. It is possible to enhance the functionality of components before and after initialization.
/// </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.聚合服务。如果需要将多个服务聚合到某一个接口组成满足业务逻辑,可以新建一个接口 如下: Aggregation services. If multiple services need to be aggregated into a single interface to meet business logic, a new interface can be created as follows

/// <summary>
/// 聚合服务特性。只能标记在接口上,不需要实现类。聚合服务不会被任何其他的代理类代理,同时也不受到IBeanPostProcessor的增强。
/// 聚合服务定义接口一定要是同步方法,异步方法暂不支持。
/// Aggregation service characteristics. It can only be marked on an interface and does not require an implementation class.
/// The aggregation service will not be proxied by any other proxy class, nor will it be enhanced by IBeanPostProcessor.
/// The aggregation service definition interface must be a synchronous method, and asynchronous methods are currently not supported.
/// </summary>
public AggregateServiceAttribute(LifeTimeType lifetime = LifeTimeType.Default)
{
    Lifetime = lifetime;
}


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

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

7.指定类的构造方法。 请注意:如果指定构造函数,则此类的类代理不会生效!则此类的类代理不会生效!则此类的类代理不会生效!

/// <summary>
/// Autofac注入时默认使用参数最多的构造函数,使用此特性指定所使用的构造函数。
/// 请注意:如果使用此特性指定构造函数,即便在拦截器内的GetInterceptorTypes()方法内声明代理此类,此类的类代理也不会生效。
/// 无参构造函数上标记此特性无效。
/// 此特性在同一个类中只能有一个。
/// 非构造函数指明此特性无效。
/// By default, the constructor with the most parameters is used during Autofac injection, and this attribute is used to specify the constructor to be used.
/// Please note that if this attribute is used to specify a constructor, even if a proxy class is declared within the GetInterceptorTypes() method within the interceptor, the class proxy for this class will not take effect.
/// This attribute is not valid when marked on an unarmed constructor.
/// This attribute can only have one in the same class.
/// Non constructor indicates that this attribute is invalid.
/// </summary>
[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
public class ConstructorAttribute:Attribute
{
}
  1. 对实例的生命周期内事件进行增强。
/// <summary>
/// Bean增强特性。可指定组件在实例激活完成之后(所有的依赖注入工作完成后)立即执行组件内的某个方法。
/// Bean enhanced features. You can specify that a component immediately executes a method within the component after the instance activation is completed (after all dependency injection work is completed).
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnActivatedAttribute : Attribute
{
}

/// <summary>
/// bean增强特性。可指定组件在实例激活时(指仅执行了构造函数),立即执行组件内的某个方法。
/// Bean enhancement features. You can specify that a component immediately executes a method within the component when the instance is activated (referring to only executing the constructor).
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class OnActivatingAttribute : Attribute
{

}

/// <summary>
/// bean增强特性。可指定某个组件在容器销毁之前执行某个方法。需要注意的是,组件销毁时依赖注入上下文已经销毁,所以此增强方式仅支持无参方法。
/// Bean enhancement features. You can specify a component to execute a method before the container is destroyed. It should be noted that the dependency injection context has already been destroyed when the component is destroyed, so this enhancement only supports parameter free methods.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class OnReleaseAttribute : Attribute
{
}

8.简单代码示例 新建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) };
   }
    //最新版已经在基类加入了默认实现,不再需要写一次了。如果有特殊需求,可以override此方法。
    //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();
}

所有服务注册时必须加入相应特性,否则无法注入成功(包括控制器)。All services must incorporate corresponding features when registering, otherwise injection cannot be successful (including controllers)

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 110 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

1.支持特性DependsOn,用于在某个组件初始化之前优先初始化部分依赖组件。在使用构造函数初始化组件时,优先将先初始化的组件注入到构造函数。使用属性或字段注入方式将不会受到影响,默认注入最后一个注册的组件。