ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

.NET 5完全自配置服务

2022-01-22 15:02:02  阅读:160  来源: 互联网

标签:ServiceLocator 服务 IFooRepository 配置 services NET type public


目录

介绍

背景

使用代码

兴趣点


介绍

在ASP.Core应用程序(不限于ASP.Core)中,当我们想使用DI容器中的构建时,我们需要创建服务,然后在Startup.cs的ConfigureServices方法中注册它们。我想简化它并在完全自注册服务中采用旧的M.E.F方法。

方法很简单:

  1. 使用[Service]或[SingeltonService]特性注释您的服务
  2. 调用 ServiceLocator.LoadServices
  3. 获益?

背景

这个想法来自现在已经过时的方法扩展框架(M.E.F.),它是.Nets (First?) DI容器的方法,这种基于注解的服务发现很流行。

使用代码

首先让我们来看看这两个特性:

[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class SingeltonServiceAttribute : ServiceAttribute
{
    public SingeltonServiceAttribute(params Type[] registerAs) : base(registerAs)
    {
        
    }
}
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class ServiceAttribute : Attribute
{
    public ServiceAttribute(params Type[] registerAs)
    {
        RegisterAs = registerAs;
    }

    public IEnumerable<Type> RegisterAs { get; set; }
}

它们都是代表我们的服务标记的属性,但也包括一个Type列表来表达声明类型应该注册的所有类型。现在让我们注释一个服务:

[SingeltonService(typeof(IFooRepository), typeof(IDatabaseRepository))]
public class FooRepository : IFooRepository
{
    public string Connection { get; set; }
    public async Task DoStuff() { }
}

public interface IFooRepository : IDatabaseRepository
{
    Task DoStuff();
}

public interface IDatabaseRepository
{
    string Connection { get; set; }
}

这将我们标记FooRepository为单例服务,但也请求IFooRepository并且IDatabaseRepository也应该指向同一个实例。因此,如果我们请求FooRepository或IFooRepository或 IDatabaseRepository,我们总是得到相同的实例(因为单例服务)。

由于我们现在已经注册了服务,让我们在我们的ServiceLocator帮助下将其加载到DI容器中:

public static class ServiceLocator
{
    public static void LoadServices(IServiceCollection services)
    {
        foreach (var type in AppDomain.CurrentDomain.GetAssemblies().SelectMany
                (f => f.GetTypes())
            .Where(e => e.GetCustomAttribute<ServiceAttribute>(false) != null))
        {
            var serviceAttribute = type.GetCustomAttribute<ServiceAttribute>(false);
            var actorTypes = serviceAttribute.RegisterAs;

            if (serviceAttribute is SingeltonServiceAttribute)
            {
                services.AddSingleton(type);
                foreach (var actorType in actorTypes)
                {
                    services.AddSingleton(actorType, (sCol) => sCol.GetService(type));
                }
            }
            else
            {
                services.AddScoped(type);
                foreach (var actorType in actorTypes)
                {
                    services.AddScoped(actorType, (sCol) => sCol.GetService(type));
                }
            }
        }
    }
}
public class MyStartup
{
    public MyStartup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    
    // This method gets called by the runtime. 
    // Use this method to add services to the container.
    // For more information on how to configure your application, 
    // visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        ServiceLocator.LoadServices(services);
    }
}

就是这样。调用ServiceLocator.LoadServices启动Service发现并加载所有服务。

兴趣点

在更大的项目中,该ConfigurateServices方法可以增长很多,如果应该配置自身的服务(DI规则)也可以注入自身,我发现它非常有用。

这不是配置服务的任何其他方式所独有的,应该与手动注册一起运行良好。

https://www.codeproject.com/Tips/5311615/Completely-Selfconfigurating-Service-with-NET-5

标签:ServiceLocator,服务,IFooRepository,配置,services,NET,type,public
来源: https://blog.csdn.net/mzl87/article/details/122634301

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有