AutoRegistDependency 2.0.1
dotnet add package AutoRegistDependency --version 2.0.1
NuGet\Install-Package AutoRegistDependency -Version 2.0.1
<PackageReference Include="AutoRegistDependency" Version="2.0.1" />
<PackageVersion Include="AutoRegistDependency" Version="2.0.1" />
<PackageReference Include="AutoRegistDependency" />
paket add AutoRegistDependency --version 2.0.1
#r "nuget: AutoRegistDependency, 2.0.1"
#addin nuget:?package=AutoRegistDependency&version=2.0.1
#tool nuget:?package=AutoRegistDependency&version=2.0.1
AutoRegistDependency
介绍
AutoFac 二次封装, 实现根据特性自动注入功能。 Based on AutoFac development, achieve automatic injection function according to characteristics.
使用说明
nuget 搜索 AutoRegistDependency 进行安装 1.055之前版本和现版本有大量改动,请参考最新文档
1. 注册服务 Registration Services
program.cs文件中 (.net6以上)
builder.Host.ConfigureContainer<ContainerBuilder>((hostBuilderContext, containerBuilder) =>
{
var r=new Register(context);
//r.GlobalLifeTime; 设置全局生命周期(特性上的生命周期优先,默认为scope)
//r.GlobalPropertyInjectType; 设置全局注入类型(默认支持构造函数和属性(字段)注入)
//r.GlobalRegistrationType;设置全局注入实例类型(默认为当前类和其自身实现的接口)
//r.EnableEventBus;//设置是否启用事件总线功能(默认开启)
//r.EnableQuartz;//设置是否启用quartz定时任务功能
//r.RegistrationInitializer;//自定义容器内实例信息定义实现类。如果需要自定义扫描到类型并注册实例信息,自定义实现接口IRegistrationInitializer并修改此属性的值即可
builder.RegisterModule(r);
});
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)=>
{
var r=new Register(context);
//r.GlobalLifeTime; 设置全局生命周期(特性上的生命周期优先)
r.GlobalPropertyInjectType;
builder.RegisterModule(r);
})
.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();
ApplicationContainer = builder.Build();
return new AutofacServiceProvider(ApplicationContainer);//将autofac反馈到管道中
}
如何支持xml,ini等配置文件的读取,需要在program.cs文件中加入代码:
WebApplicationBuilder? builder = WebApplication.CreateBuilder(args);
//.net7 以上
builder.Configuration.AddJsonFile();//增加读取json文件
builder.Configuration.AddJsonStream();//增加读取json文件流
builder.Configuration.AddIniFile();//增加读取ini文件
builder.Configuration.AddIniStream();//增加读取ini文件流
builder.Configuration.AddXmlFile();//增加读取xml文件
builder.Configuration.AddXmlStream();//增加读取xml文件流
//.net 6 以下
builder.Host.ConfigureAppConfiguration((context, config) =>
{
config.AddJsonFile();//增加读取json文件
config.AddJsonStream();//增加读取json文件流
config.AddIniFile();//增加读取ini文件
config.AddIniStream();//增加读取ini文件流
config.AddXmlFile();//增加读取xml文件
config.AddXmlStream();//增加读取xml文件流
})
WPF使用方法如下: 1.引入包 Microsoft.Extensions.Hosting,Microsoft.Extensions.Hosting.Abstractions 2.修改 App.xaml的生成操作为页 3.重写 App的main函数
public partial class App : Application
{
[STAThread]
static void Main(string[] args)
{
using IHost host = CreateHost(args);
var app=new App();
var context= host.Services.GetService<IComponentContext>();
host.Start();
app.MainWindow= context?.Resolve<MainWindow>();
app.MainWindow!.Visibility = Visibility.Visible;
app.InitializeComponent();
app.Run();
}
static IHost CreateHost(string[] args)
{
var builder = Host.CreateDefaultBuilder(args);
//builder.ConfigureAppConfiguration((context, builder) =>
//{
// builder.AddJsonFile("appsettings.json");
//});
builder.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.ConfigureContainer<ContainerBuilder>((hostBuilderContext, containerBuilder) =>
{
containerBuilder.RegisterModule(new Register(hostBuilderContext, "WpfApp1"));
});
//这些配置和WebApi的完全一样
builder.ConfigureServices(service =>
{
service.AddSerilog(lc =>
{
lc.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.Enrich.WithProcessId()
.Enrich.WithThreadId()
.Enrich.WithExceptionDetails()
.Enrich.WithEnvironmentUserName()
.WriteTo.Console()
.WriteTo.File(Path.Combine("logs", @"log.txt"), restrictedToMinimumLevel: LogEventLevel.Information, rollingInterval: RollingInterval.Day);
});
});
var host = builder.Build();
host.Services.QuartzRegist();
return host;
}
}
如何实现页面的导航跳转,以WPF UI 为例子 1.实现接口 INavigationViewPageProvider
[Component]
public class NavigationViewPageProvider : INavigationViewPageProvider
{
private readonly IComponentContext context;
public NavigationViewPageProvider(IComponentContext context)
{
this.context = context;
}
public object? GetPage(Type pageType)
{
return context.Resolve(pageType);
}
}
2.在有Navigation子组件的地方注入此接口,构造函数内对 NavigationView 的PageService赋值
[Component]
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : FluentWindow
{
private MainWindowViewModel mainWindowViewModel;
private INavigationViewPageProvider navigationViewPageProvider;
public MainWindow(MainWindowViewModel mainWindowViewModel, INavigationViewPageProvider navigationViewPageProvider)
{
this.navigationViewPageProvider = navigationViewPageProvider;
DataContext = mainWindowViewModel!;
InitializeComponent();
Loaded += (sender, args) =>
{
SystemThemeWatcher.Watch(
this, // Window class
WindowBackdropType.Mica, // Background type
true // Whether to change accents automatically
);
};
//RootNavigation 这个东西就是xaml里面的组件Name
RootNavigation.SetPageProviderService(navigationViewPageProvider);
this.mainWindowViewModel = mainWindowViewModel;
}
}
强烈建议WPF使用构造函数的方式进行注入操作,如果部分逻辑需要在构造函数内实现,使用[Autowire]注入的服务无法获取!
特别说明:此组件默认读取系统的IConfignature服务获取配置文件数据,默认支持nacos读取json文件(如果nacos注册成功的话)
2. 特性说明 (1.0.55版本之前采用构造函数的方式指定参数,现在通过公共属性)
ComponentAttribute 只能标记在类上,代表此类型需要被自动注入
ConfigurationPropertiesAttribute 只能标记在类上,代表此类型是通过配置文件读取并进行实例绑定
ConfigurationAttribute 只能标记在类上,代表此类被容器单例管理,通常配合bean使用
JobAttribute 仅能标记在类上,代表此类为Quartz的任务类(此类必须实现Quartz的Ijob接口,否则会报错!多个cron表达式用';'分隔)
BeanAttribute 只能标记在方法上,代表此方法返回的实例需要被管理 (此方法的类上未标记ConfigurationAttribute无效!!)
AutowiredAttribute 可以标记在属性、字段上以及方法上 代表此属性(字段)将注入到实例中
ComponentFilterAttribute 标记在构造函数参数上,通过此特性标注构造函数注入的服务的key或者name
ValueAttribute 可标记在属性,字段和参数上。代表被标记的对象需要从配置文件中自动读取数据
OrderAttribute 标记在类上,代表服务注册的顺序 越小越先注册
RegistrationAsAttribute 标记在类上,代表此服务以何种类型注册(如果不是注册类型的父类或者注册类型所实现的接口,在注册初始化时将会报错)
ConditionalAttribute 标记在类上或者方法上(支持多个特性打在同一目标),代表注册此服务是有条件的,conditionTypes为实现接口ICondition的实现类。如果hostBuilderContext为空的话,不会执行conditional特性所指定的类
ConditionalOnPropertyAttribute 标记在类上或者方法上(支持多个特性打在同一目标),代表此服务的注册依赖于读取配置文件的值
ConditionalOnBeanAttribute 当容器内存在指定的组件时,才会注册此组件
ConditionalOnMissBeanAttribute 当容器内缺少指定组件,才注册此组件
DependsOnAttribute 标记此组件实例化之前需要初始化其他的组件并缓存。在使用构造函数的方式注入依赖时,优先使用缓存内的实例。如果标记了ComponentFilterAttribute 特性,指定的参数将不会使用缓存内实例。如果使用的是属性或者字段注入,此方式将不起作用,只能起到优先初始化其他参数的作用。
3. 动态代理注册方法
继承抽象类 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
{
}
8. 对实例的生命周期内事件进行增强(实例在容器内创建的不同生命周期,执行标记的指定方法)。
/// <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
{
}
9.简单代码示例
新建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 | Versions 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. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.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. |
-
.NETStandard 2.0
- Autofac (>= 8.3.0)
- Autofac.Extensions.DependencyInjection (>= 10.0.0)
- Autofac.Extras.DynamicProxy (>= 7.1.0)
- Castle.Core.AsyncInterceptor (>= 2.1.0)
- Microsoft.CSharp (>= 4.7.0)
- Microsoft.Extensions.Configuration (>= 9.0.6)
- Microsoft.Extensions.Configuration.Binder (>= 9.0.6)
- Microsoft.Extensions.DependencyModel (>= 9.0.6)
- Microsoft.Extensions.Hosting.Abstractions (>= 9.0.6)
- Quartz (>= 3.14.0)
- System.Runtime.Loader (>= 4.3.0)
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 |
---|---|---|
2.0.1 | 141 | 6/23/2025 |
2.0.0 | 103 | 6/20/2025 |
1.0.55 | 232 | 9/6/2024 |
1.0.54 | 175 | 6/5/2024 |
1.0.53 | 142 | 6/5/2024 |
1.0.52 | 128 | 5/21/2024 |
1.0.50 | 198 | 4/24/2024 |
1.0.49 | 149 | 4/23/2024 |
1.0.48 | 154 | 2/28/2024 |
1.0.47 | 168 | 1/23/2024 |
1.0.46 | 210 | 12/5/2023 |
1.0.45 | 237 | 9/8/2023 |
1.0.44 | 212 | 8/23/2023 |
1.0.43 | 176 | 8/10/2023 |
1.0.42 | 182 | 6/26/2023 |
1.0.41 | 186 | 5/23/2023 |
1.0.40 | 243 | 4/18/2023 |
1.0.39 | 234 | 4/14/2023 |
1.0.38 | 231 | 4/11/2023 |
1.0.37 | 237 | 4/11/2023 |
1.0.36 | 252 | 4/3/2023 |
1.0.35 | 271 | 3/16/2023 |
1.0.34 | 300 | 3/6/2023 |
1.0.32 | 281 | 3/3/2023 |
1.0.31 | 290 | 3/2/2023 |
1.0.30 | 295 | 3/2/2023 |
1.0.29 | 290 | 3/1/2023 |
1.0.28 | 304 | 2/25/2023 |
1.0.27 | 301 | 2/22/2023 |
1.0.26 | 292 | 2/22/2023 |
1.0.25 | 290 | 2/21/2023 |
1.0.24 | 289 | 2/20/2023 |
1.0.23 | 289 | 2/17/2023 |
1.0.22 | 364 | 2/15/2023 |
1.0.21 | 320 | 2/13/2023 |
1.0.20 | 312 | 2/9/2023 |
1.0.19 | 315 | 2/9/2023 |
1.0.18 | 324 | 2/7/2023 |
1.0.17 | 299 | 2/7/2023 |
1.0.16 | 293 | 2/7/2023 |
1.0.15 | 315 | 2/4/2023 |
1.0.14 | 328 | 2/2/2023 |
1.0.13 | 348 | 1/31/2023 |
1.0.12 | 333 | 1/31/2023 |
1.0.11 | 327 | 1/31/2023 |
1.0.10 | 360 | 1/30/2023 |
1.0.9 | 346 | 1/30/2023 |
1.0.8 | 343 | 1/30/2023 |
1.0.5 | 342 | 1/28/2023 |
1.0.4 | 358 | 1/28/2023 |
1.0.3 | 355 | 1/23/2023 |
1.0.2 | 359 | 1/21/2023 |
1.0.1 | 359 | 1/17/2023 |
1.0.0 | 357 | 1/17/2023 |
1.定时任务特性支持多cron表达式
3.注册器的全局属性通过属性修改,而不是通过方法
4.修改readme