.net 源码中设计模式的应用

.net core 中的经典设计模式的应用

Intro

前段时间我们介绍了23种设计模式,今天来分享一下 .net core 源码中我觉得比较典型的设计模式的应用

实例

责任链模式

asp.net core 中间件的设计就是责任链模式的应用和变形,

每个中间件根据需要处理请求,并且可以根据请求信息自己决定是否传递给下一个中间件,我也受此启发,封装了一个 PipelineBuilder 可以轻松构建中间件模式代码,可以参考这篇文章 https://www.cnblogs.com/weihanli/p/12700006.html

中间件示例:

app.UseStaticFiles();app.UseResponseCaching();app.UseResponseCompression();app.UseRouting();app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());app.UseAuthentication();app.UseAuthorization();app.UseEndpoints(endpoints =>{ endpoints.MapControllers(); endpoints.MapControllerRoute(name: "areaRoute", "{area:exists}/{controller=Home}/{action=Index}"); endpoints.MapDefaultControllerRoute();});

PipelineBuilder 实际示例:

var requestContext = new RequestContext(){ RequesterName = "Kangkang", Hour = 12,};var builder = PipelineBuilder.Create<RequestContext>(context =>  {   Console.WriteLine($"{context.RequesterName} {context.Hour}h apply failed");  })  .Use((context, next) =>  {   if (context.Hour <= 2)   {    Console.WriteLine("pass 1");   }   else   {    next();   }  })  .Use((context, next) =>  {   if (context.Hour <= 4)   {    Console.WriteLine("pass 2");   }   else   {    next();   }  })  .Use((context, next) =>  {   if (context.Hour <= 6)   {    Console.WriteLine("pass 3");   }   else   {    next();   }  }) ;var requestPipeline = builder.Build();foreach (var i in Enumerable.Range(1, 8)){ Console.WriteLine(); Console.WriteLine($"--------- h:{i} apply Pipeline------------------"); requestContext.Hour = i; requestPipeline.Invoke(requestContext); Console.WriteLine("----------------------------"); Console.WriteLine();}

建造者模式

asp.net core 中的各种 Builder, HostBuilder/ConfigurationBuilder 等,这些 Builder 大多既是 Builder 又是 Director,Builder 本身知道如何构建最终的 Product(Host/Configuration)

var host = new HostBuilder() .ConfigureAppConfiguration(builder => {  // 注册配置  builder   .AddInMemoryCollection(new Dictionary<string, string>()   {    {"UserName", "Alice"}   })   .AddJsonFile("appsettings.json")   ; }) .ConfigureServices((context, services) => {  // 注册自定义服务  services.AddSingleton<IIdGenerator, GuidIdGenerator>();  services.AddTransient<IService, Service>();  if (context.Configuration.GetAppSetting<bool>("XxxEnabled"))  {   services.AddSingleton<IUserIdProvider, EnvironmentUserIdProvider>();  } }) .Build() ;

工厂模式

依赖注入框架中有着大量的工厂模式的代码,注册服务的时候我们可以通过一个工厂方法委托来获取服务实例,

依赖注入的本质就是将对象的创建交给 IOC 容器来处理,所以其实 IOC 容器本质就是一个工厂,从 IOC 中获取服务实例的过程就是工厂创建对象的过程,只是会根据服务的生命周期来决定是创建新对象还是返回已有对象。

services.AddSingleton(sp => new Svc2(sp.GetRequiredService<ISvc1>(), "xx"));

单例模式

在 dotnet 中有一个 TimeQueue 的类型,纯正的饿汉模式的单例模式代码

class TimerQueue{ #region singleton pattern implementation // The one-and-only TimerQueue for the AppDomain. static TimerQueue s_queue = new TimerQueue(); public static TimerQueue Instance {  get { return s_queue; } } private TimerQueue() {  // empty private constructor to ensure we remain a singleton. } #endregion // ...}

https://referencesource.microsoft.com/#mscorlib/system/threading/timer.cs,49

在 dotnet 源码中还有一些懒汉式的单例模式

使用 Interlocked 原子操作

internal class SimpleEventTypes<T> : TraceLoggingEventTypes{ private static SimpleEventTypes<T> instance; internal readonly TraceLoggingTypeInfo<T> typeInfo; private SimpleEventTypes(TraceLoggingTypeInfo<T> typeInfo)  : base(   typeInfo.Name,   typeInfo.Tags,   new TraceLoggingTypeInfo[] { typeInfo }) {  this.typeInfo = typeInfo; } public static SimpleEventTypes<T> Instance {  get { return instance ?? InitInstance(); } } private static SimpleEventTypes<T> InitInstance() {  var newInstance = new SimpleEventTypes<T>(TraceLoggingTypeInfo<T>.Instance);  Interlocked.CompareExchange(ref instance, newInstance, null);  return instance; }}

另外一个示例,需要注意,下面这种方式不能严格的.........