.Net Core-自定义组件封装,委托的初始化和分派

在研究Core源码过程中,发现在封装自定义组件时用了很多委托的概念,使代码更加简洁高效

 

委托目前的使用场景目前分为两个:

1)扩展自定义组件(委托的初始化)

2)避免类库之间的循环调用依赖(委托的分派)

准备工作:

委托是什么?是一种引用类型,用于将方法作为参数传递给其他方法

委托简单例子:

 1 //定义委托
 2 private delegate int CaculateDelegate(int x, int y);
 3 static void Main(string[] args)
 4 {
 5     //实例化委托
 6     CaculateDelegate caculateDelegate =new CaculateDelegate(Add);
 7 
 8     //调用委托
 9     Console.WriteLine(caculateDelegate.Invoke(2, 1));
10 
11     Console.WriteLine("Hello World!");
12 
13     Console.ReadLine();
14 }
15 
16 static int Add(int x, int y)
17 { 
18     return x + y;
19 }
结果:

补充Action和Func的委托声明:

 1 //Action声明委托 可接受0-16个传入参数,无返回值
 2 Action<int,int> calaction=new Action<int,int>(Add_Action);
 3 calaction.Invoke(2, 1);
 4 
 5 //Func声明委托 接受0-16个传入参数,必须有返回值
 6 Func<int,int,int> calfun = new Func<int, int,int>(Add);
 7 Console.WriteLine(calfun.Invoke(2, 2));
 8 
 9  //Action声明委托 Lamada表达式
10 Action<int, int> callamadaaction = ((a, b) => { Console.WriteLine(a + b); });
11 callamadaaction.Invoke(2, 2);
12 
13 //Action参数传递
14 TestAdd(callamadaaction, 3, 3);
15 Console.WriteLine("Funcs!");
16 
17 
18 static void TestAdd(Action<int, int> action,int input1,int input2)
19 {
20     action(input1, input2);
21 }

1)扩展自定义组件-委托初始化

这里我们以邮件发送功能为例

增加邮件的扩展方法,AddMyEmailSevice.cs

 1 public static IServiceCollection AddMyEmailSevice(this IServiceCollection services, Action<EmailSettings> configAction)
 2 {
 3 
 4     EmailSettings emailSettings = new EmailSettings();
 5     configAction.Invoke(emailSettings); 
 6     services.AddSingleton<IC2FactoryEmail, C2FactoryEmail>(sp =>
 7                                                            {
 8                                                                return new C2FactoryEmail(emailSettings);
 9                                                            });
10     return services;
11 }

传入参数Action<EmailSettings> configAction. 这里的EmailSettings是邮件配置的Model类。

在ConfigurationService调用邮件扩展方法,通过Action的Lamada方式初始化EmailSettings的值。在AddMyEmailSevice中,configAction.Invoke触发该初始化方法。

1 services.AddMyEmailSevice(config => {
2       config.FromMail= Configuration.GetSection("EmailSetting:FromMail").Value;
3       config.Authorization = Configuration.GetSection("EmailSetting:Authorization").Value;
4       config.Emailtype = (EmailType)Enum.Parse(typeof(EmailType), Configuration.GetSection("EmailSetting:Emailtype").Value)  ;
5       config.IsBodyHtml = Configuration.GetSection("EmailSetting:IsBodyHtml").Value=="true"?true:false;
6       config.ToMailList = Configuration.GetSection("EmailSetting:ToMailList").Value;
7   });

该方法好处是不需要关心是如何初始化,触发Invoke时机可以自己定义

2)避免类库的循环依赖-委托分派

如图所示:有两个类库Uni_Common和Uni_FLK

其中Uni_FLK的UserService登陆时,记录登陆日志,调用LogHelper的AddLog

1 public void Login(string username, string password)
2 {
3     Console.WriteLine("Login Success!");
4 
5     LogHelper.AddLog("登陆成功");
6 }

LogHelper实现AddLog时,需要引用Uni_FLK中的LogService,这样就造成了循环依赖

1 public class LogHelper
2     {
3         public static void AddLog(string message)
4         {
5             //要写入数据库  要引用Uni_FLK中的LogService
6         } 
7     }

通过委托来解决这个问题,在LogHelper中重载AddLog

public class LogHelper
{
    public static void AddLog(string message)
    {
        //要写入数据库  要引用Uni_FLK中的LogService
    }

    public static void AddLog(string message, Action<string> writeInDB)
    {
        writeInDB(message);
    }
}

UserService调用如下:

1 LogHelper.AddLog("登陆成功", message =>
2                  {
3 
4                      LogService.WriteLogInDB(message);
5                  });

运行结果:

 

 

总结:

了解委托的基本概念和几种使用方式。

有返回值使用Fun<T>,没有返回值使用Action<T>。

从对Net Core组件的邮件发送功能进行扩展,使用委托对配置进行初始化。通过委托分派解决类库间循环依赖的问题。

 

以上,仅用于学习和总结!

posted @ 2022-01-04 20:43  y_w_k  阅读(313)  评论(0编辑  收藏  举报