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

.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 中的各种 BuilderHostBuilder/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;
    }
}

另外一个示例,需要注意,下面这种方式不能严格的保证只会产生一个实例,在并发较高的情况下可能不是同一个实例,这也可以算是工厂模式的一个示例

static internal class ConfigurationManagerHelperFactory 
{
    private const string ConfigurationManagerHelperTypeString = "System.Configuration.Internal.ConfigurationManagerHelper, " + AssemblyRef.System;


    static private volatile IConfigurationManagerHelper s_instance;


    static internal IConfigurationManagerHelper Instance {
        get {
            if (s_instance == null) {
                s_instance = CreateConfigurationManagerHelper();
            }


            return s_instance;
        }
    }


    [ReflectionPermission(SecurityAction.Assert, Flags = ReflectionPermissionFlag.MemberAccess)]
    [SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification = "Hard-coded to create an instance of a specific type.")]
    private static IConfigurationManagerHelper CreateConfigurationManagerHelper() {
        return TypeUtil.CreateInstance<IConfigurationManagerHelper>(ConfigurationManagerHelperTypeString);
    }
}

原型模式

dotnet 中有两个数据结构 Stack/Queue 这两个数据都实现了 ICloneable 接口,内部实现了深复制 来看 StackClone 方法实现:

public virtual Object Clone()
{
    Contract.Ensures(Contract.Result<Object>() != null);
 
    Stack s = new Stack(_size);
    s._size = _size;
    Array.Copy(_array, 0, s._array, 0, _size);
    s._version = _version;
    return s;
}

详细可以参考:https://referencesource.microsoft.com/#mscorlib/system/collections/stack.cs,6acda10c5f8b128e

享元模式

string intern(字符串池),以及 Array.Empty<int>()/Array.Empty<string>()

策略模式

asp.net core 中的认证和授权,我觉得就是策略模式的应用,在使用 [Authorize] 的时候会使用默认的 policy,也可以指定要使用的策略 [Authorize("Policy1")] 这样就会使用另外一种策略 Policy1,policy 还是比较简单的

policy 是用来根据用户的认证信息来控制授权访问的,而认证则是根据当前上下文(请求上下文、线程上下文、环境上下文等)的信息进行认证从而获取用户信息的过程

而不同的认证模式(Cookie/JWT/自定义Token等)其实是不同的处理方法,也就是策略模式中不同的算法实现,指定哪种认证模式,就是使用哪种算法实现来获取用户信息

观察者模式

常使用事件(event)进行解耦,外部代码通过订阅事件来解耦,实现对内部状态的观察

Process 类中有很多事件,可以用来捕获另一个进程中的输出,错误等

public event DataReceivedEventHandler OutputDataReceived;


public event DataReceivedEventHandler ErrorDataReceived;

通常这两个事件我们就可以获取到另外一个进程中的输出信息,除此之外还有很多的类在使用事件,相信你也用过很多

组合模式

WPF、WinForm 中都有控件的概念,这些控件的设计属于是组合模式的应用,所有的控件都会继承于某一个共同的基类, 使得单个对象和组合对象都可以看作是他们共同的基类对象

迭代器模式

c# 中定义了迭代器模式,原始定义:

// 聚集抽象
public interface IEnumerable
{
    /// <summary>Returns an enumerator that iterates through a collection.</summary>
    /// <returns>An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.</returns>
    IEnumerator GetEnumerator();
}


// 迭代器抽象
public interface IEnumerator
{
    /// <summary>Advances the enumerator to the next element of the collection.</summary>
    /// <returns>
    /// <see langword="true" /> if the enumerator was successfully advanced to the next element; <see langword="false" /> if the enumerator has passed the end of the collection.</returns>
    /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created.</exception>
    bool MoveNext();


    /// <summary>Gets the element in the collection at the current position of the enumerator.</summary>
    /// <returns>The element in the collection at the current position of the enumerator.</returns>
    object Current { get; }


    /// <summary>Sets the enumerator to its initial position, which is before the first element in the collection.</summary>
    /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created.</exception>
    void Reset();
}

Array 和 List 各自实现了自己的迭代器,感兴趣可以去看下源码

More

.net core 中的设计模式应用还有很多,不仅上面提到的这几个模式,也不仅仅是我所提到的这几个地方

上面有一些示例是直接用的 dotnet framework 中的源码,因为有很多代码都是类似的,用的 https://referencesource.microsoft.com 的源码

以上均是个人理解,如果有错误还望指出,十分感谢,欢迎补充更多设计模式应用的源码实例

Reference

  • https://github.com/dotnet/aspnetcore

  • https://github.com/dotnet/extensions

  • https://github.com/dotnet/corefx

  • https://github.com/dotnet/aspnetcore

  • https://github.com/dotnet/runtime

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ASP.NET Core 3.1是一个跨平台、高性能的开源框架,它可以帮助我们快速地构建Web应用程序。ASP.NET Core 3.1文教程可以为初学者提供一个快速上手的指南,帮助他们了解和掌握该框架的各种功能。 在学习ASP.NET Core 3.1教程之前,我们需要了解一些基本的编程概念和技能, 包括C#语言的基础知识、MVC(Model View Controller)等常见的编程模式、以及前端技术如HTML、CSS和JavaScript等。此外,我们还需要对.NET Core框架有一定的了解,如.NET Core的概念、架构和基础组件等。 学习ASP.NET Core 3.1的教程需要深入理解其设计方案和特点,例如跨平台、高性能、依赖注入、实时通信等。此外,我们还需要熟悉其主要组件,如ASP.NET Core间件、MVC框架、Entity Framework Core等。 在学习ASP.NET Core 3.1的教程时,我们需要通过实践才能更好地理解其所涉及的技术和概念。因此,我们需要通过编写各种实际的Web应用程序和示例,来实践和掌握所学的技巧和知识。 总之,学习ASP.NET Core 3.1的文教程需要较深的前置知识储备和实操经验,而且需要坚持不懈地学习和练习以提高自己的技能水平。 ### 回答2: ASP.NET Core 3.1是目前为止最新的ASP.NET Core版本,它是一个跨平台的Web应用程序开发框架。对于想要学习ASP.NET Core 3.1的开发者来说,文教程是非常重要的。 现在,有很多文教程可以帮助开发者快速入门ASP.NET Core 3.1。这些教程通常包括以下内容: 1. ASP.NET Core 3.1的基础知识:网页处理、路由、控制器等; 2. ASP.NET Core 3.1的模型、视图和控制器; 3. 动作过滤器和特性; 4. 实体框架和数据库相关操作; 5. API设计和测试等。 这些教程通常包含实例和练习,能够帮助开发者深入理解ASP.NET Core 3.1的开发原理。另外,一些知名的在线教育平台,如网易云课堂等,也提供了ASP.NET Core 3.1的文课程,有兴趣的开发者可以去尝试。 总的来说,学习ASP.NET Core 3.1需要投入时间和精力,但是文教程能够让初学者更加轻松地掌握ASP.NET Core 3.1的开发技能,更好地进行ASP.NET Core 3.1的开发工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值