ASP.NET Core 3.1系列(25)——Autofac中的泛型注册和程序集注册

32 篇文章 43 订阅

1、前言

在实际开发业务中,泛型的应用非常广泛,而这也就产生了一个问题:泛型类和泛型接口该怎么注册?难道要开发者一行一行去写泛型构造参数吗?同时,实际业务中往往也会对项目进行分层设计,例如接口层、实现层。对于这种处于不同程序集的接口和类,又有没有什么高效的方法对其进行处理呢?本文就来介绍一下如何利用Autofac来处理这两类问题。

2、Autofac中的泛型注册

新建泛型接口、泛型类、实体类,代码如下:

public interface IService<TEntity> where TEntity : class
{
    string Get();
}

public class Service<TEntity> : IService<TEntity> where TEntity : class
{
    public string Get()
    {
        return typeof(TEntity).FullName;
    }
}

public class Cat { }
public class Dog { }

如果使用Autofac中的基础注册方法,代码如下:

using Autofac;
using System;

namespace App
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 注册接口和类
            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterType<Service<Cat>>().As<IService<Cat>>();
            builder.RegisterType<Service<Dog>>().As<IService<Dog>>();

            // 构建容器
            IContainer container = builder.Build();

            // Cat
            IService<Cat> cat = container.Resolve<IService<Cat>>();
            Console.WriteLine(cat.Get());

            // Dog
            IService<Dog> dog = container.Resolve<IService<Dog>>();
            Console.WriteLine(dog.Get());
        }
    }
}

运行结果如下所示:

App.Cat
App.Dog

上面的代码虽然实现了泛型注册,但问题也是显而易见的:一旦实体类数量较多,开发者需要手写大量注册代码。在Autofac中,我们可以使用RegisterGeneric方法来实现泛型注册,代码如下:

using Autofac;
using System;

namespace App
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 注册接口和类
            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterGeneric(typeof(Service<>)).As(typeof(IService<>));

            // 构建容器
            IContainer container = builder.Build();

            // Cat
            IService<Cat> cat = container.Resolve<IService<Cat>>();
            Console.WriteLine(cat.Get());

            // Dog
            IService<Dog> dog = container.Resolve<IService<Dog>>();
            Console.WriteLine(dog.Get());
        }
    }
}

使用RegisterGeneric方法的好处就是无需写大量的带泛型构造参数的注册代码。运行结果如下所示:

App.Cat
App.Dog

3、Autofac中的程序集注册

在实际业务中,一般会对项目进行分层设计。下图显示了一个简易的分层项目:

在这里插入图片描述

Repository层代码如下所示:

namespace App.Repository.Contract
{
    public interface ICatRepository
    {
        string GetCatMsg();
    }
}
namespace App.Repository.Contract
{
    public interface IDogRepository
    {
        string GetDogMsg();
    }
}
using App.Repository.Contract;

namespace App.Repository
{
    public class CatRepository : ICatRepository
    {
        public string GetCatMsg()
        {
            return "This is cat";
        }
    }
}
using App.Repository.Contract;

namespace App.Repository
{
    public class DogRepository : IDogRepository
    {
        public string GetDogMsg()
        {
            return "This is dog";
        }
    }
}

Service层代码如下所示:

namespace App.Service.Contract
{
    public interface ICatService
    {
        string Get();
    }
}
namespace App.Service.Contract
{
    public interface IDogService
    {
        string Get();
    }
}
using App.Repository.Contract;
using App.Service.Contract;

namespace App.Service
{
    public class CatService : ICatService
    {
        protected readonly ICatRepository _repository;

        public CatService(ICatRepository repository)
        {
            _repository = repository;
        }

        public string Get()
        {
            return _repository.GetCatMsg();
        }
    }
}
using App.Repository.Contract;
using App.Service.Contract;

namespace App.Service
{
    public class DogService : IDogService
    {
        protected readonly IDogRepository _repository;

        public DogService(IDogRepository repository)
        {
            _repository = repository;
        }

        public string Get()
        {
            return _repository.GetDogMsg();
        }
    }
}

如果使用Autofac的基础注册方法,可以写成如下形式:

using App.Repository;
using App.Repository.Contract;
using App.Service;
using App.Service.Contract;
using Autofac;
using System;

namespace App
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 注册接口和类
            ContainerBuilder builder = new ContainerBuilder();
            builder.RegisterType<CatRepository>().As<ICatRepository>();
            builder.RegisterType<DogRepository>().As<IDogRepository>();
            builder.RegisterType<CatService>().As<ICatService>();
            builder.RegisterType<DogService>().As<IDogService>();

            // 构建容器
            IContainer container = builder.Build();

            // ICatService
            ICatService cat = container.Resolve<ICatService>();
            Console.WriteLine(cat.Get());

            // IDogService
            IDogService dog = container.Resolve<IDogService>();
            Console.WriteLine(dog.Get());
        }
    }
}

运行结果如下所示:

This is cat
This is dog

上面的代码虽然能够实现注册,但其实问题跟泛型注册一样:如果有很多接口和类,那么就需要写大量重复代码。一般来说,分层项目会对各层中的文件命名做一定的限制。例如,仓储层中的文件必须以Repository结尾,服务层中的文件必须以Service结尾。这就给我们提供了一个思路:能否通过加载程序集批量获取文件名称,通过文件名称的匹配来实现接口和类的注册?其实,Autofac中的RegisterAssemblyTypes方法就支持这么做,代码如下:

using App.Service.Contract;
using Autofac;
using System;
using System.Reflection;

namespace App
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 注册接口和类
            ContainerBuilder builder = new ContainerBuilder();

            // 注册Repository
            Assembly repository = Assembly.Load("App.Repository");
            Assembly repositoryContract = Assembly.Load("App.Repository.Contract");
            builder.RegisterAssemblyTypes(repository, repositoryContract)
                   .Where(p => p.Name.EndsWith("Repository"))
                   .AsImplementedInterfaces();

            // 注册Service
            Assembly service = Assembly.Load("App.Service");
            Assembly serviceContract = Assembly.Load("App.Service.Contract");
            builder.RegisterAssemblyTypes(service, serviceContract)
                   .Where(p => p.Name.EndsWith("Service"))
                   .AsImplementedInterfaces();

            // 构建容器
            IContainer container = builder.Build();

            // ICatService
            ICatService cat = container.Resolve<ICatService>();
            Console.WriteLine(cat.Get());

            // IDogService
            IDogService dog = container.Resolve<IDogService>();
            Console.WriteLine(dog.Get());
        }
    }
}

运行结果如下所示:

This is cat
This is dog

程序集注册的好处是显而易见的:如果后续需要添加新的接口和类,我们也不需要修改代码,因为Autofac会自动扫描类库中文件,然后通过名称匹配进行注册。

4、结语

本文主要介绍了Autofac中的泛型注册和程序集注册,这两种注册方法具有非常高的实用性。如果你对项目进行了分层设计,同时项目中也存在大量泛型接口和泛型类,那么使用泛型注册和程序集注册将会达到事半功倍的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值