翼度科技»论坛 编程开发 .net 查看内容

.Net 一套接口多实现

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
.Net 一套接口多实现

接口(interface)可理解为规范、标准、协议。接口是用来约束各方都在同一组规范下工作。
电脑外设USB接口,各个品牌商家生产的U盘、鼠标都能够被电脑主板识别并工作,这是因为个生产商都遵循实现了USB接口协议。
在编程中接口应用非常广泛,例如IDbConnection接口,这是一组数据库连接的接口,由各个数据库驱动实现,因此.Net可以操作多种数据库。
一套接口多实现的基本结构如下

实现思路是,通过在各实现类上使用Attribute进行标记,然后定义一个实例获取类,通过反射获取所有实现该接口并且标记了的实现类,并将各个实现类通过IOC注册,然后通过标记的类型获取对应的实现类。
接下来是demo演示
定义服务标记
  1.     [AttributeUsageAttribute(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
  2.     public class MultiServiceTypeAttribute : Attribute
  3.     {
  4.         public string ServiceType { get; private set; }
  5.         public MultiServiceTypeAttribute(string serviceType)
  6.         {
  7.             ServiceType = serviceType;
  8.         }
  9.     }
复制代码
定义接口IMultiInterface
  1.     public interface IMultiInterface
  2.     {
  3.         void Do();
  4.     }
复制代码
定义实现类AMultiInterfaceImplA并标记
  1.     [MultiServiceTypeAttribute("A")]
  2.    public class MultiInterfaceImplA : IMultiInterface
  3.     {
  4.         public void Do()
  5.         {
  6.             Console.WriteLine("这是A实现的调用");
  7.         }
  8.     }
复制代码
定义实现类BMultiInterfaceImplB并标记
  1.     [MultiServiceTypeAttribute("B")]
  2.     public class MultiInterfaceImplB : IMultiInterface
  3.     {
  4.         public void Do()
  5.         {
  6.             Console.WriteLine("这是B实现的调用");
  7.         }
  8.     }
复制代码
将接口与实现添加到IOC容器,这里使用 Microsoft.Extensions.DependencyInjection.dll和Microsoft.Extensions.DependencyInjection.Abstractions.dll两个库来实现简易IOC容器
  1.     public class ServiceLoader
  2.     {
  3.         private readonly ServiceCollection __ioc = new ServiceCollection();
  4.         private ServiceProvider __iocServiceProvider;
  5.         private static object _lock = new object();
  6.         private static ServiceLoader _inst;
  7.         public static ServiceLoader Inst
  8.         {
  9.             get
  10.             {
  11.                 if (_inst == null)
  12.                 {
  13.                     lock (_lock)
  14.                     {
  15.                         if (_inst == null)
  16.                         {
  17.                             _inst = new ServiceLoader();
  18.                             _inst.Init();
  19.                         }
  20.                     }
  21.                 }
  22.                 return _inst;
  23.             }
  24.         }
  25.         private void Init()
  26.         {
  27.             var tps = typeof(IMultiInterface).Assembly.GetTypes().Where(x =>
  28.                   x.GetInterfaces().Any(_ => _.Name == nameof(IMultiInterface)));
  29.             foreach (var item in tps)
  30.             {
  31.                 if (item.IsClass)
  32.                 {
  33.                     Inst.AddTransient(typeof(IMultiInterface), item);
  34.                 }
  35.             }
  36.             Interlocked.Exchange(ref __iocServiceProvider, Inst.__ioc.BuildServiceProvider());
  37.         }
  38.         private void AddTransient(Type iface, Type impl)
  39.         {
  40.             __ioc.AddTransient(iface, impl);
  41.         }
  42.     }
复制代码
根据标记的类型获取对应的接口实现。在ServiceLoader中继续添加以下方法
  1.         public IMultiInterface GetService(string serviceType)
  2.         {
  3.             var svcList = __iocServiceProvider.GetServices<IMultiInterface>();
  4.             var svc = svcList.FirstOrDefault(x => x.GetType().GetCustomAttribute<MultiServiceTypeAttribute>()?.ServiceType == serviceType);
  5.             if (svc == null)
  6.             {
  7.                 //Console.WriteLine($@"未找到 {serviceType} 服务实现,使用默认实现");
  8.                 // 如果有默认实现类,这里可选择调用默认实现
  9.                 //svc = svcList.FirstOrDefault(x => x.GetType().GetCustomAttribute<MultiServiceTypeAttribute>()?.ServiceType == "__default__");
  10.                 throw new Exception($"未找到 {serviceType} 服务实现");
  11.             }
  12.             return svc;
  13.         }
复制代码
通过ServiceLoader.Inst.GetService("serviceType").Do();来获取对应的接口实例,入参就是各个实现类上标记的类型,并调用接口。
调用示例如下

至此实现了一接口多实现的雏形。

来源:https://www.cnblogs.com/ycit/archive/2023/07/21/17571500.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具