D-10 AoP ? autofac ? DynamicProxy

Service怎麽做到像MiddleWare一样的东西

在网页程序中可以透过MiddleWare来做到关注点分离,但是那是在请求中可以去拦截跟处理请求,如果今天脚色换成Service之类的程序该如何处理呢,这就是我们今天要介绍的内容AoP。

本文同步放置於此

AoP

「天啊~~~我要怎麽处理每个方法的输入输出的log阿。」
一进办公室小光就听到大头的惨叫声,因为大头昨天在追一个bug追到没有方向,所以今天一大早大头决定要先把每个方法加上输入跟输出的log。
「你知道甚麽是AoP吗」
听到大头的惨叫後老K这麽问题,这时大头像找到救星一般脸上露出了曙光。
「前辈,救救我吧。」
所以今天就跟着小光还有大头了解一下甚麽是AoP以及在dotnetcore做到AoP。

甚麽是AoP

AoP就是剖面导向程序设计,白话文就是如同关注点分离,对於开发的程序关注於本身的逻辑开发,而其他与本身逻辑无关的功能就从程序中抽离,然後在像切蛋糕一样切开来把额外的功能加到程序内,就如同一开始的大头在本身的程序内没有日志的功能,所以现在我们在拦截原来的程序并在这里加入日志的功能。不过说那麽多在dotnetcore内该如何处理呢,接下来我们介绍DynamicProxy这个套件。

DynamicProxy

所以我们在dotnetcore中实作AoP就是透过dynamicproxy这个套件,所以接下来我们说明如何透过autofac及dynamicproxy做到AoP。

环境处理

在介绍如何撰写程序做到AoP之前先说明我们需要使用到哪些套件,接下来我们先安装以下两个套件即可。

dotnet add package Autofac.Extras.DynamicProxy
dotnet add package Autofac.Extensions.DependencyInjection

实作拦截者

在安装完套件之後我们开始来开发AoP,首先假设我们的需求是开发一个寄送email的服务,但是我们需要输入及输出的参数,所以我们先定义介面以及实作。

public interface IEmailService
{
     string Send(string message);
}

[Intercept(typeof(CallLogger))]
public class EmailService : IEmailService
{
    public string Send(string message)
    {
        return message;
    }
}

在实作时我们透过Intercept这个属性来注入拦截者,接下来说明拦截者怎麽实作。

public class CallLogger : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine($"You are invoke {invocation.Method.Name}, args:{JsonSerializer.Serialize(invocation.Arguments)}");
        invocation.Proceed();
        Console.WriteLine($"You are finished {invocation.Method.Name}, result:{JsonSerializer.Serialize(invocation.ReturnValue)}");
    }
}

主要拦截者就是继承IInterceptor并实作public void Intercept(IInvocation invocation)这个方法,这边注意invocation.Proceed();就是执行被拦截的方法,所以我们把需要做的需求写在那方法之前跟之後即可。最後来说明如何注册拦截者跟本来的程序。

builder.Register(c => new CallLogger());
builder.RegisterType<EmailService>().As<IEmailService>().InstancePerDependency().EnableInterfaceInterceptors();

插入拦截器的方法有下列两种。

EnableClassInterceptors 产生一个类别继承要拦截的类别,所以方法要加virtual才能拦截
EnableInterfaceInterceptors 动态产生一个代理接口

除了透过Attribute之外,还可以在注入时加上,所以注入拦截器的方法有下列两种。

加Attribute [Intercept(typeof(CallLogger))]
注入拦截器 builder.RegisterType().As().InterceptedBy(typeof(CallLogger)).InstancePerDependency().EnableInterfaceInterceptors();

後记

透过AoP可以把一般物件中做到关注点分离,如此不只在处理请求中,甚至於在处理一般的函式都可以专注在该函式主要处理的逻辑上,而其它非需要关注的逻辑就抽到拦截者来处理。


<<:  Day 20 - Valid Anagram

>>:  DAY23: 自定义模块

Day17 CSS Media Query

在了解Media Queries的用法之前,先来了解一些RWD的观念吧。 RWD是什麽? RWD是...

3.Git管理unity专案

使用Git管理专案,进行版本控制(version control) 剩下的27天为了预防万一,我将采...

Day08 NAT 穿透 ICE、STUN、TURN

ICE ICE(Interactive Connectivity Establishment,互动式...

Day 12 - Semigroup I

Definition of a Semigroup 一个集合(Set)或称型别(Type) 有 co...

[DSA] - Basic ADT (Arrays, Linked List, Stack)

Abstract Data Type (ADT) Human - Interface - ADT L...