.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是一个 ...
随机推荐
- SpringBoot自定义cron表达式注册定时任务
springBoot自定义cron表达式注册定时任务 一.原理 1.使用Spring自带的TaskScheduler注册任务 2.注册后返回:ScheduledFuture,用于取消定时任务 3.注册 ...
- javasec(五)URLDNS反序列化分析
这篇文章介绍 URLDNS 就是ysoserial中⼀个利⽤链的名字,但准确来说,这个其实不能称作"利⽤链".因为其参数不是⼀个可以"利⽤"的命令,⽽仅为⼀个U ...
- 深度学习--魔法类nn.Module
深度学习--魔法类nn.Module 作用 pytorch 封装了一些基本的网络类,可以直接调用 好处: 可以直接调用现有的类 容器机制:self.net = nn.Sequential() 参数返回 ...
- JVM有意思的图-持续更新
放一些JVM有意思的图 通过一行代码联想JVM:
- Python_13 接口测试openpyxl和表操作
一.openpyxl 安装 pip install openpyxl 在Terminal中输入 excel操作步骤 找到目标excel 打开 读取数据.编辑excel单元格 保存 关闭 open ...
- Python网络爬虫原理及实践
作者:京东物流 田禹 1 网络爬虫 网络爬虫:是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本. 网络爬虫相关技术和框架繁多,针对场景的不同可以选择不同的网络爬虫技术. 2 Scrapy框架( ...
- PaddlePaddle 飞桨复现 ResNeXt
import paddle.nn as nn import paddle class BN_Conv2D(nn.Layer): """ BN_CONV_RELU &quo ...
- STL------sort三种比较算子定义
sort的三种比较算子的定义方式 例:一道细碎的细节模拟题: http://newoj.acmclub.cn/contests/1258/problem/3 1932: 2018蓝桥杯培训-STL应用 ...
- Django4全栈进阶之路5 Model模型
在 Django 中,模型(Model)是用于定义数据结构的组件,其作用如下: 定义数据结构:模型用于定义数据库中的表格和表格中的字段(列),其中每个模型类对应一个表格,模型中的每个字段对应表格中的一 ...
- python学习之-------OS 文件夹和文件操作
# OS模块 :查看一个文件夹下所有文件,这个文件夹有文件夹,不能用walk# -- coding: UTF-8 --import osimport sys#C:\Users\Administrato ...