.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组件的邮件发送功能进行扩展,使用委托对配置进行初始化。通过委托分派解决类库间循环依赖的问题。
以上,仅用于学习和总结!