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

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

至此实现了一接口多实现的雏形。
.Net 一套接口多实现的更多相关文章
- Linux网络编程系列-套接口选项控制
获取和设置套接口选项的方法有: getsockopt/setsockopt fcntl ioctl getsockopt/setsockopt 这两个函数仅用于套接口(socket)的设置,另外两个函 ...
- UDP套接口编程
常用的UDP实现的程序:DNS域名系统,NFS网络文件系统,SNMP简单网络管理协议 ssize_t recvfrom(int sockfd,void *buff,size_t nbytes,int ...
- fuser:用文件或者套接口表示进程
fuser:用文件或者套接口表示进程 作用:fuser命令用文件或者套接口表示进程. 用法:fuser [-a | -s | -c] [-4 | -6] [-n space] [-k [-i] [-s ...
- socket , 套接口还是套接字,傻傻分不清楚
socket 做网络通信的朋友大都对socket这个词不会感到陌生,但是它的中文翻译是叫套接口还是套接字呢,未必大多数朋友能够分清,今天我们就来聊聊socket的中文名称. socket一词的起源 在 ...
- Socket调用Close后如何终止套接口的问题
setsockopt 设置 SO_LINGER 选项 此选项指定函数close对面向连接的协议如何操作(如TCP).内核缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数 ...
- 值得收藏的TCP套接口编程文章
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由jackieluo发表于云+社区专栏 TCP客户端-服务器典型事件 下图是TCP客户端与服务器之间交互的一系列典型事件时间表: 首先启 ...
- 设置套接口的选项setsockopt的用法
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- 套接口socket编程(Client/Server编程实例)
基本概念 套接口也就是网络中的ID.网络通信,归根到底还是进程间通信(不同计算机上的进程间的通信).在网络中,每一个节点(计算机或路由器)都有一个网络地址,也就是IP地址. IP地址:在网络中唯一标识 ...
- UNIX网络编程读书笔记:原始套接口
概述 应用程序可以绕过传输层而直接使用IPv4和IPv6,这称为原始套接口(raw socket).http://www.cnblogs.com/nufangrensheng/p/3583435.ht ...
- UNIX网络编程读书笔记:基本SCTP套接口编程
概述 SCTP是一个较新的传输协议,于2000年在IETF得到标准化(TCP是在1981年标准化的).它最初是为满足不断增长的IP电话市场设计的:具体地说,就是穿越因特网传输电话信令. SCTP是一个 ...
随机推荐
- Django 静态文件 request对象方法 pycharm和Django连接MySQL Django模型层初步了解 基本的ORM操作
目录 静态文件 一.概念 静态文件:不经常变化的文件,主要针对html文件所使用到的各种资源. 例如:css文件.js文件.img文件.第三方框架文件 ps: Django针对静态文件资源需要单独在根 ...
- Qt+MySql开发笔记:Qt5.9.3的msvc2017x64版本编译MySql8.0.16版本驱动并Demo连接数据库测试
前言 mysql驱动版本msvc2015x32版本调好, mysql的mingw32版本的驱动上一个版本编译并测试好,有些三方库最低支持vs2017,所以只能使用msvc2017x64,基于Qt5 ...
- [双目视差] 立体匹配-SGBM半全局立体匹配算法
立体匹配-SGBM半全局立体匹配算法 一.SGBM算法实现过程 1.预处理 预处理目的是得到图像的梯度信息 Step1:SGBM采用水平Sobel算子,对图像做处理,公式为: Sobel(x,y)=2 ...
- 一文梳理z-index和层叠上下文
前言 最近参与某前端项目架构改造,发现项目中滥用z-index,设置的值有几十种并且不统一.在对项目的z-index进行梳理和统一过程中也深入学习了一下z-index,并撰写成文,希望也能帮助到陌生的 ...
- 民谣女神唱流行,基于AI人工智能so-vits库训练自己的音色模型(叶蓓/Python3.10)
流行天后孙燕姿的音色固然是极好的,但是目前全网都是她的声音复刻,听多了难免会有些审美疲劳,在网络上检索了一圈,还没有发现民谣歌手的音色模型,人就是这样,得不到的永远在骚动,本次我们自己构建训练集,来打 ...
- 2022-03-24:你被请来给一个要举办高尔夫比赛的树林砍树,树林由一个 m x n 的矩阵表示, 在这个矩阵中: 0 表示障碍,无法触碰 1 表示地面,可以行走 比 1 大的数 表示有树的单元格,
2022-03-24:你被请来给一个要举办高尔夫比赛的树林砍树,树林由一个 m x n 的矩阵表示, 在这个矩阵中: 0 表示障碍,无法触碰 1 表示地面,可以行走 比 1 大的数 表示有树的单元格, ...
- 2021-05-01:给定一个有序数组arr,代表坐落在X轴上的点。给定一个正数K,代表绳子的长度。返回绳子最多压中几个点?即使绳子边缘处盖住点也算盖住。
2021-05-01:给定一个有序数组arr,代表坐落在X轴上的点.给定一个正数K,代表绳子的长度.返回绳子最多压中几个点?即使绳子边缘处盖住点也算盖住. 福大大 答案2021-05-01: 滑动窗口 ...
- LVDS_33 support
在HR bank/HD bank中,支持LVDS的bank使用VCCO 3.3v供电,仅仅需要对端给过来的信号,满足标准的LVDS差模电压/共模电压的标准即可.如下截图: 限制: 仅能作为input ...
- vue自定义组件——search-box
pre { overflow-y: auto; max-height: 300px } github地址: https://github.com/lxmghct/my-vue-components 组 ...
- Vue 异步通信Axios
使用Axios实现异步通信需要先导入cdn: <script src="https://unpkg.com/axios@1.4.0/dist/axios.min.js"> ...