type
status
date
slug
summary
tags
category
icon
password
Property
Sep 1, 2023 12:49 PM

本节内容

反射与依赖注入
反射:以不变应万变(更松的耦合)
反射与接口的结合
反射与特性的结合
依赖注入:此DI非彼DI,没有彼DI就没有此DI

接口隔离

违反单一职责原则,类就很“胖”,很“大”
违反接口隔离原则
namespace ConsoleApp6 { internal class Program { static void Main(string[] args) { var driver = new Driver(new Car()); driver.Drive(); var driver2 = new Driver2(new HeavyTank()); driver2.Drive(); } } class Driver { private IVehicle _vehicle; public Driver(IVehicle vehicle) { _vehicle = vehicle; } public void Drive() { _vehicle.Run(); } } class Driver2 { private ITank _tank; public Driver2(ITank tank) { _tank = tank; } public void Drive() { _tank.Run(); } } interface IVehicle { void Run(); } class Car : IVehicle { public void Run() { Console.WriteLine("Car in running..."); } } class Truck : IVehicle { public void Run() { Console.WriteLine("Truck in running..."); } } interface ITank { void Fire(); void Run(); } class LightTank : ITank { public void Fire() { Console.WriteLine("LightTank Boom!"); } public void Run() { Console.WriteLine("LightTank in running..."); } } class MediumTank : ITank { public void Fire() { Console.WriteLine("MediumTank Boom!"); } public void Run() { Console.WriteLine("MediumTank in running..."); } } class HeavyTank : ITank { public void Fire() { Console.WriteLine("HeavyTank Boom!"); } public void Run() { Console.WriteLine("HeavyTank in running..."); } } }
一个类只能继承一个接口,但是一个接口可以有多个基接
namespace ConsoleApp6 { internal class Program { static void Main(string[] args) { var driver = new Driver(new Car()); driver.Drive(); var driver2 = new Driver(new HeavyTank()); driver2.Drive(); } } class Driver { private IVehicle _vehicle; public Driver(IVehicle vehicle) { _vehicle = vehicle; } public void Drive() { _vehicle.Run(); } } interface IVehicle { void Run(); } class Car : IVehicle { public void Run() { Console.WriteLine("Car in running..."); } } class Truck : IVehicle { public void Run() { Console.WriteLine("Truck in running..."); } } interface IWeapon { void Fire(); } interface ITank : IVehicle, IWeapon { } class LightTank : ITank { public void Fire() { Console.WriteLine("LightTank Boom!"); } public void Run() { Console.WriteLine("LightTank in running..."); } } class MediumTank : ITank { public void Fire() { Console.WriteLine("MediumTank Boom!"); } public void Run() { Console.WriteLine("MediumTank in running..."); } } class HeavyTank : ITank { public void Fire() { Console.WriteLine("HeavyTank Boom!"); } public void Run() { Console.WriteLine("HeavyTank in running..."); } } }
第二种,参数的接口太胖,比如我只想要run,没有必要引入IWeapon接口
调用者绝不多要,提供者绝不少给。
using System.Collections; namespace ConsoleApp6 { internal class Program { static void Main(string[] args) { int[] nums1 = { 1, 2, 3, 4, 5 }; ArrayList nums2 = new ArrayList { 1, 2, 3, 4, 5 }; Console.WriteLine(Sum(nums1)); Console.WriteLine(Sum(nums2)); var nums3 = new ReadOnlyCollection(nums1); Console.WriteLine(Sum(nums3)); foreach (int i in nums3) { Console.WriteLine(i); } } static int Sum(IEnumerable nums) { int sum = 0; foreach (int i in nums) { sum += i; } return sum; } } class ReadOnlyCollection : IEnumerable { private int[] _array; public ReadOnlyCollection(int[] array) { _array=array; } public IEnumerator GetEnumerator() { return new Enumerator(this); } public class Enumerator : IEnumerator { private ReadOnlyCollection _collection; private int _head; public Enumerator(ReadOnlyCollection collection) { _collection = collection; _head = -1; } public object Current { get { object o = _collection._array[_head]; return o; } } public bool MoveNext() { if(++_head< _collection._array.Length) { return true; } else { return false; } } public void Reset() { _head = -1; } } } }
第三种:接口的显式实现
using System.Collections; namespace ConsoleApp6 { internal class Program { static void Main(string[] args) { var wk=new WarmKiller(); // 不能看到Kill方法 wk.Love(); IKiller killer = wk; // 能看到Kill方法,看不到Love killer.Kill(); // 调用Love的方法 var wk1 = killer as WarmKiller; wk1?.Love(); // 或者 ((WarmKiller)killer).Love(); } } interface IGentleman { void Love(); } interface IKiller { void Kill(); } class WarmKiller : IGentleman,IKiller { /* 实例都可以调用 * public void Kill() { Console.WriteLine("Let me kill the enemy..."); }*/ public void Love() { Console.WriteLine("I will love you forever..."); } // 显式实现,还有吧实例当做IKiller实例的时候,才能调用 void IKiller.Kill() { Console.WriteLine("Let me kill the enemy..."); } } }

反射

以不变应万变
过多使用反射机制,会影响性能
反射的基本原理
using System.Reflection; namespace ConsoleApp6 { internal class Program { static void Main(string[] args) { ITank tank = new HeavyTank(); // =========== // 不碰静态类型,从内存读出描述 // 反射的基本原理 var t = tank.GetType(); object o=Activator.CreateInstance(t); MethodInfo fireMI = t.GetMethod("Fire"); MethodInfo runMI = t.GetMethod("Run"); fireMI.Invoke(o, null); runMI.Invoke(o, null); } } class Driver { private IVehicle _vehicle; public Driver(IVehicle vehicle) { _vehicle = vehicle; } public void Drive() { _vehicle.Run(); } } interface IVehicle { void Run(); } class Car : IVehicle { public void Run() { Console.WriteLine("Car in running..."); } } class Truck : IVehicle { public void Run() { Console.WriteLine("Truck in running..."); } } interface IWeapon { void Fire(); } interface ITank : IVehicle, IWeapon { } class LightTank : ITank { public void Fire() { Console.WriteLine("LightTank Boom!"); } public void Run() { Console.WriteLine("LightTank in running..."); } } class MediumTank : ITank { public void Fire() { Console.WriteLine("MediumTank Boom!"); } public void Run() { Console.WriteLine("MediumTank in running..."); } } class HeavyTank : ITank { public void Fire() { Console.WriteLine("HeavyTank Boom!"); } public void Run() { Console.WriteLine("HeavyTank in running..."); } } }

DIP 依赖反转,DI依赖注入

接口的实现者就是服务提供者
using System.Reflection; using Microsoft.Extensions.DependencyInjection; namespace ConsoleApp6 { internal class Program { static void Main(string[] args) { // 就是容器 var sc = new ServiceCollection(); sc.AddScoped(typeof(ITank), typeof(MediumTank)); // 自动注入 sc.AddScoped(typeof(IVehicle), typeof(LightTank)); sc.AddScoped<Driver>(); var sp=sc.BuildServiceProvider(); //==================== ITank tank=sp.GetService<ITank>(); tank.Fire(); tank.Run(); // 自动找依赖 var driver=sp.GetService<Driver>(); driver.Drive(); } } class Driver { private IVehicle _vehicle; public Driver(IVehicle vehicle) { _vehicle = vehicle; } public void Drive() { _vehicle.Run(); } } interface IVehicle { void Run(); } class Car : IVehicle { public void Run() { Console.WriteLine("Car in running..."); } } class Truck : IVehicle { public void Run() { Console.WriteLine("Truck in running..."); } } interface IWeapon { void Fire(); } interface ITank : IVehicle, IWeapon { } class LightTank : ITank { public void Fire() { Console.WriteLine("LightTank Boom!"); } public void Run() { Console.WriteLine("LightTank in running..."); } } class MediumTank : ITank { public void Fire() { Console.WriteLine("MediumTank Boom!"); } public void Run() { Console.WriteLine("MediumTank in running..."); } } class HeavyTank : ITank { public void Fire() { Console.WriteLine("HeavyTank Boom!"); } public void Run() { Console.WriteLine("HeavyTank in running..."); } } }

更松的耦合,插件式编程。

插件:不与主体程序一起编译,但是可以和主体一起工作的组件。好处是以主体程序为中心,生成生态圈。
API: Application Programming Interface
SDK: Software Development Kit
动物小程序
using System.Reflection; using Microsoft.Extensions.DependencyInjection; using System.IO; using System.Runtime.Loader; namespace ConsoleApp6 { internal class Program { static void Main(string[] args) { Console.WriteLine(Environment.CurrentDirectory); var folder = Path.Combine(Environment.CurrentDirectory, "Animals"); var files = Directory.GetFiles(folder); var animalsTypes = new List<Type>(); foreach (var file in files) { var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file); var types = assembly.GetTypes(); foreach (var t in types) { animalsTypes.Add(t); } } while (true) { for (int i = 0; i < animalsTypes.Count; i++) { Console.WriteLine($"{i + 1}.{animalsTypes[i].Name}"); } Console.WriteLine("===================="); Console.WriteLine("Please choose animal."); int index = int.Parse(Console.ReadLine()); if (index > animalsTypes.Count || index < 1) { Console.WriteLine("No such an animal.Try again!"); continue; } Console.WriteLine("How many times?"); int times = int.Parse(Console.ReadLine()); var t = animalsTypes[index - 1]; var m = t.GetMethod("Voice"); var o = Activator.CreateInstance(t); m.Invoke(o, new object[] { times }); } } } }
namespace ClassLibrary1 { public class Cat { public void Voice(int times) { for (int i = 0; i < times; i++) { Console.WriteLine("miao~"); } } } }
namespace ClassLibrary2 { public class Dog { public void Voice(int times) { for (int i = 0; i < times; i++) { Console.WriteLine("Wang~"); } } } }
C#知识学习—24 接口,依赖反转,单元测试C#知识学习—26 泛型,partial类,枚举,结构体
Loading...
Kitety
Kitety
独特为佳,Kitety的个人博客
公告
我曾经七次鄙视自己的灵魂
--卡里·纪伯伦
第一次,当它本可进取时,却故作谦卑;
第二次,当它在空虚时,用爱欲来填充;
第三次,在困难和容易之间,它选择了容易;
第四次,它犯了错,却借由别人也会犯错来宽慰自己;
第五次,它自由软弱,却把它认为是生命的坚韧;
第六次,当它鄙夷一张丑恶的嘴脸时,却不知那正是自己面具中的一副;
第七次,它侧身于生活的污泥中,虽不甘心,却又畏首畏尾。
 
支持在线微信赞赏扶贫
notion image
 
最新评论
Loading...