為啥要用DI
之前有寫一篇實現DIP原則,主要就是把類別的屬性、方法設計在介面中,然後讓一個類別去繼承這個介面實作出來,讓產生的實例依賴在介面上去符合DIP,使用的時候大概是長這樣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Program { static void Main(string[] args) {
ISendMail instance = new SendMail(); instance.Send(); } }
public class SendMail : ISendMail { }
public interface ISendMail { }
|
看起來是符合DIP了,程式也更有彈性,但是還是有一個new SendMail()的動作,看著還是跟SendMail類別聯繫在一起,所以就有注入依賴這個東西
怎麼用
函數庫
nuget 安裝 Microsoft.Extensions.DependencyInjection
實際使用
我原本看網路上教學都這樣寫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Program { static void Main(string[] args) { ServiceCollection collection = new ServiceCollection(); collection.TryAddSingleton<ILog, Logger>(); collection.BuildServiceProvider().GetService<ILog>().Log(); } }
public class Logger : ILog { public void Log() { Console.WriteLine("do log"); } }
public interface ILog { public void Log(); }
|
把介面跟實做的方法注入到DI容器中,把new的動作改成每次在呼叫GetService()的時候產生實例,原本以為這樣已經很牛逼了,直到我看到了這個做法
在MailServiceLogger類別中已經完全看不到實做ILog這個動作了,雖然還是跟ILog、Logger注入到同一個容器中,但這對我來說它真正的跟實做這件事情分開了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| class Program { static void Main(string[] args) { ServiceCollection collection = new ServiceCollection(); collection.TryAddTransient<MailServiceLogger>(); collection.TryAddTransient<ILog, Logger>(); var mailserviceLogger = collection.BuildServiceProvider().GetService<MailServiceLogger>(); mailserviceLogger.Log();
} }
public class MailServiceLogger { private ILog _log; public MailServiceLogger(ILog log) { _log = log; }
public void Log() { _log.Log(); } }
public class Logger : ILog { public DateTime InstanceCreateTime { get; set; } public Logger() { this.InstanceCreateTime = DateTime.Now; }
public string getCreateTime() { return this.InstanceCreateTime.ToString(); }
public void Log() { Console.WriteLine("do log"); } }
public interface ILog { public void Log(); }
|