30_接口隔离,反射,特性,依赖注入

接口隔离原则:

如果存在具有完全覆盖关系的多个接口(胖瘦接口),会出现这多个接口之间不兼容情况,所以使用接口继承方式解决

设计失误:把太多的功能包含在一个接口里面
● 这就导致实现该接口的类违反了单一职责原则
○ 单一职责原则:一个类只做一件(或一组相关的)事
● 接口隔离原则是从服务调用者的角度来看接口类型,单一职责原则是从服务提供者的角度来看接口类型
● 解决方案就是把胖接口拆成单一的小接口(把本质不同的功能隔离开)

显式实现接口:
显式实现接口时,只有该实例被作为该接口类型进行转换时才能调用该接口的方法

class Demo_Partition3
    {
        public void test()
        {
            WarmKiller warmKiller = new WarmKiller();
            (warmKiller as IKiller).Kill();
        }
    }

    interface IGentleman
    {
        void Love();
    }

    interface IKiller
    {
        void Kill();
    }

    class WarmKiller : IGentleman, IKiller
    {
        

        public void Love()
        {
            Console.WriteLine("love");
        }

        void IKiller.Kill()//显式实现接口
        {
            throw new NotImplementedException();
        }
    }

反射
反射:你给我一个对象,我能在不用 new 操作符也不知道该对象的静态类型的情况下,我能给你创建出一个同类型的对象,还能访问该对象的各个成员。

这相当于进一步的解耦,因为有 new 操作符后面总得跟类型,一跟类型就有了紧耦合的依赖。依靠反射创建类型不再需要 new 操作符也无需静态类型,这样使得很多时候耦合可以松到忽略不计。

结合显式调用接口做了一波测试

	class Demo_Partition3
    {
        public void test()
        {
            WarmKiller warmKiller = new WarmKiller();
            (warmKiller as IKiller).Kill();

            Type t = warmKiller.GetType();
            object o = Activator.CreateInstance(t);
            MethodInfo killMethod = t.GetInterface(typeof(IKiller).Name).GetMethod("Kill");
            MethodInfo loveMethod = t.GetMethod("Love");
            killMethod.Invoke((IKiller)o, null);
            loveMethod.Invoke(o, null);
        }
    }

    interface IGentleman
    {
        void Love();
    }

    interface IKiller
    {
        void Kill();
    }

    class WarmKiller : IGentleman, IKiller
    {
        

        public void Love()
        {
            Console.WriteLine("love");
        }

        void IKiller.Kill()//显式实现接口
        {
            Console.WriteLine("kill");
        }
    }

依赖注入:
个人理解类似于牵线,服务已经为你设定好了需要哪些东西时对应的提供项,缺啥就从里面找,自动为你形成一套创建过程

			var sc = new ServiceCollection();
            sc.AddScoped(typeof(ITank), typeof(Demo30_HeavyTank));
            sc.AddScoped(typeof(IVehecle), typeof(Demo30_MedianTank));
            sc.AddScoped<Demo30_Driver>();
            var sp = sc.BuildServiceProvider();

            Demo30_Driver demo30_Driver1 = sp.GetService<Demo30_Driver>();
            demo30_Driver1.Drive();

实操案例:
因为项目采用.net framework架构,如果读取的是.net core的类库会报错(囧)

namespace watch_learn_CSharp
{
    class Demo_Reflection_Depencies_Injection
    {
        public void test()
        {
            var folder = Path.Combine(Environment.CurrentDirectory, "Animals");
            var files = Directory.GetFiles(folder);
            var animalTypes = new List<Type>();
            //Console.WriteLine(files.Length);
            
            foreach (var item in files)//读文件
            {
                var assembly = Assembly.LoadFrom(item);//读程序集
                var types = assembly.GetTypes();//读程序集中的所有类型
                foreach (var type in types)//若有可以发声的类
                {
                    if (type.GetMethod("Voice") != null)
                    {
                        animalTypes.Add(type);
                    }
                }
            }
            while (true)
            {
                int count = 0;
                foreach (var item in animalTypes)
                {
                    Console.WriteLine($"{++count}:{item.Name}");
                }

                int index = int.Parse(Console.ReadLine());
                if (index < count)
                {
                    int times = int.Parse(Console.ReadLine());
                    var t = animalTypes[index - 1];
                    var m = t.GetMethod("Voice");
                    m.Invoke(Activator.CreateInstance(t),new object[] { times});//这里是object数组,里面包含了不定量的实参,估计没有对应的参数列表时会报错
                }
                else
                {
                    Console.WriteLine("No such an animal.Try again!");
                }
            }
        }
    }
}

第一方准备SDK之后,你再在这个基础上建立程序集……

主程序:

class Demo_Reflection_Depencies_Injection
    {
        public void test()
        {
            var folder = Path.Combine(Environment.CurrentDirectory, "Animals");
            var files = Directory.GetFiles(folder);
            var animalTypes = new List<Type>();
            //Console.WriteLine(files.Length);
            
            foreach (var item in files)//读文件
            {
                var assembly = Assembly.LoadFrom(item);//读程序集
                var types = assembly.GetTypes();//读程序集中的所有类型
                foreach (var type in types)//若有可以发声的类
                {
                    if (type.GetInterfaces().Contains(typeof(IAnimal)) && type.GetInterface(typeof(IAnimal).ToString()) != null)//两种用法都可以,都列出来只是为了验证两者是同一作用
                    {
                        Console.WriteLine(type.Name);
                        if (!type.GetCustomAttributes(false).Any(x => x.GetType() == typeof(UnfinishedAttribute)))
                        {
                            animalTypes.Add(type);
                        }
                    }
                }
            }
            while (true)
            {
                int count = 0;
                foreach (var item in animalTypes)
                {
                    Console.WriteLine($"{++count}:{item.Name}");
                }
                Console.WriteLine("Please choose animal");
                int index = int.Parse(Console.ReadLine());
                if (index <= count)
                {
                    int times = int.Parse(Console.ReadLine());
                    var t = animalTypes[index - 1];
                    var m = t.GetMethod("Voice");
                    IAnimal animal = (IAnimal)Activator.CreateInstance(t);
                    animal.Voice(times);
                }
                else
                {
                    Console.WriteLine("No such an animal.Try again!");
                }
                Console.WriteLine("===================");
            }
        }
    }

Lib内容
因为偷懒,就直接手动添加第一方的 SDK/程序集 了……(也可以模仿上述直接读文件读程序集读类型的步骤……不对!你设计类的时候你不知道这个接口你应该怎么设计??必须手动添加SDK)
以猫为实例:

    [Unfinished]//特性
    public class Cat:IAnimal
    {
        public void Voice(int times)
        {
            for (int i = 0; i < times; i++)
            {
                Console.WriteLine("miao");
            }
        }
    }

SDK内容:
接口部分:

namespace HelpLib
{
    public interface IAnimal
    {
        void Voice(int times);
    }
}

特性定义:

public class UnfinishedAttribute:Attribute
    {

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值