介面(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();
來獲取對應的介面範例,入參就是各個實現類上標記的型別,並呼叫介面。
呼叫範例如下
至此實現了一介面多實現
的雛形。
本文來自部落格園,作者:宣君{https://www.nhit.icu/},轉載請註明原文連結:https://www.cnblogs.com/ycit/p/17571500.html