C# 反射与依赖注入

原创
2021/02/16 00:50
阅读数 222


1. 反射与依赖注入


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

1.1 接口隔离原则


1.1.1

实例:

using System;

namespace IspExample
{
   
   
   
    class Program
    {
   
   
   
        static void Main(string[] args)
        {
   
   
   
            var driver = new Driver(new Car());
            driver.Drive();

            var driver1 = new Driver(new LightTank());
            driver1.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 is running ...");
        }
    }

    class Truck : IVehicle
    {
   
   
   
        public void Run()
        {
   
   
   
            Console.WriteLine("Truck is running ...");
        }
    }

    interface IWeapon {
   
   
   
        void Fire();
    }

    /// <summary>
    /// 接口合并
    /// </summary>
    interface ITank : IVehicle, IWeapon
    {
   
   
   

    }

    class LightTank : ITank {
   
   
    
        public void Fire() {
   
   
   
            Console.WriteLine("Boom!");
        }

        public void Run() {
   
   
   
            Console.WriteLine("Ka Ka Ka ...");
        }
    }
    class MediumTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka! Ka! Ka! ...");
        }
    }
    class HeavyTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!!!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka!! Ka!! Ka!! ...");
        }
    }
}

1.1.2


实例:

using System;
using System.Collections;

namespace IspExample2
{
   
   
   
    class Program
    {
   
   
   
        static void Main(string[] args)
        {
   
   
   
            int[] nums1 = {
   
   
    1, 2, 3, 4, 5 };
            ArrayList nums2 = new ArrayList {
   
   
    1, 2, 3, 4, 5 };
            var nums3 = new ReadOnlyCollection(nums1);
            Console.WriteLine(Sum(nums1));
            Console.WriteLine(Sum(nums2));
            Console.WriteLine(Sum(nums3));
        }

        static int Sum(IEnumerable nums) {
   
   
   
            int sum = 0;
            foreach (var n in nums) {
   
   
   
                sum += (int)n;
            }
            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;
            }
        }
    }
}

1.1.3 显示接口实现


using System;

/// <summary>
/// 显示接口实现
/// </summary>
namespace IspExample3
{
   
   
   
    class Program
    {
   
   
   
        static void Main(string[] args)
        {
   
   
   
            IKiller killer = new WarmKiller();
            killer.Kill();
            var wk = (IGentleman)killer;
            wk.Love();
        }
    }

    interface IGentleman {
   
   
   
        void Love();
    }

    interface IKiller {
   
   
   
        void Kill();
    }

    class WarmKiller:IGentleman, IKiller {
   
   
   
        public void Love() {
   
   
   
            Console.WriteLine("I will love for ever ...");
        }

        void IKiller.Kill()
        {
   
   
   
            Console.WriteLine("Let me kill enemy ...");
        }
    }
}

2. 反射


  • .NET Core和.NET Framework的反射调用库不同;

实例:直接用反射

using System;
using System.Reflection;

namespace IspExample4
{
   
   
   
    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 is running ...");
        }
    }

    class Truck : IVehicle
    {
   
   
   
        public void Run()
        {
   
   
   
            Console.WriteLine("Truck is running ...");
        }
    }

    interface IWeapon
    {
   
   
   
        void Fire();
    }

    /// <summary>
    /// 接口合并
    /// </summary>
    interface ITank : IVehicle, IWeapon
    {
   
   
   

    }

    class LightTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka Ka Ka ...");
        }
    }
    class MediumTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka! Ka! Ka! ...");
        }
    }
    class HeavyTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!!!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka!! Ka!! Ka!! ...");
        }
    }
}

实例:封装好的反射
安装.NET Core的依赖注入框架
在这里插入图片描述


using System;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;

namespace IspExample4
{
   
   
   
    class Program
    {
   
   
   
        static void Main(string[] args)
        {
   
   
   
            var sc = new ServiceCollection();
            sc.AddScoped(typeof(ITank), typeof(HeavyTank));
            var sp = sc.BuildServiceProvider();
            // ===========华丽的分割线============
            ITank tank = sp.GetService<ITank>();
            tank.Fire();
            tank.Run();
        }
    }

    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 is running ...");
        }
    }

    class Truck : IVehicle
    {
   
   
   
        public void Run()
        {
   
   
   
            Console.WriteLine("Truck is running ...");
        }
    }

    interface IWeapon
    {
   
   
   
        void Fire();
    }

    /// <summary>
    /// 接口合并
    /// </summary>
    interface ITank : IVehicle, IWeapon
    {
   
   
   

    }

    class LightTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka Ka Ka ...");
        }
    }
    class MediumTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka! Ka! Ka! ...");
        }
    }
    class HeavyTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!!!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka!! Ka!! Ka!! ...");
        }
    }
}

using System;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;

namespace IspExample4
{
   
   
   
    class Program
    {
   
   
   
        static void Main(string[] args)
        {
   
   
   
            var sc = new ServiceCollection();
            sc.AddScoped(typeof(ITank), typeof(HeavyTank));
            sc.AddScoped(typeof(IVehicle), typeof(LightTank));
            sc.AddScoped<Driver>();
            var sp = sc.BuildServiceProvider();
            // ===========华丽的分割线============
            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 is running ...");
        }
    }

    class Truck : IVehicle
    {
   
   
   
        public void Run()
        {
   
   
   
            Console.WriteLine("Truck is running ...");
        }
    }

    interface IWeapon
    {
   
   
   
        void Fire();
    }

    /// <summary>
    /// 接口合并
    /// </summary>
    interface ITank : IVehicle, IWeapon
    {
   
   
   

    }

    class LightTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka Ka Ka ...");
        }
    }
    class MediumTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka! Ka! Ka! ...");
        }
    }
    class HeavyTank : ITank
    {
   
   
   
        public void Fire()
        {
   
   
   
            Console.WriteLine("Boom!!!");
        }

        public void Run()
        {
   
   
   
            Console.WriteLine("Ka!! Ka!! Ka!! ...");
        }
    }
}

2.1 反射应用


主体程序实例:

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Loader;

namespace BabyStroller.App{
   
   
   
    class Program{
   
   
   
        static void Main(string[] args){
   
   
   
            var folder = Path.Combine(Environment.CurrentDirectory, "Animals");
            var files = Directory.GetFiles(folder);
            var animalTypes = new List<Type>();
            foreach (var file in files) {
   
   
   
                var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file);
                var types = assembly.GetTypes();
                foreach (var t in types) {
   
   
   
                    if (t.GetMethod("Voice") != null) {
   
   
   
                        animalTypes.Add(t);
                    }
                }
            }

            while (true) {
   
   
   
                for (int i = 0; i < animalTypes.Count; i++) {
   
   
   
                    Console.WriteLine($"{i + 1}.{animalTypes[i].Name}");
                }
                Console.WriteLine("=====================");
                Console.WriteLine("Please choose animal:");
                int index = int.Parse(Console.ReadLine());
                if (index > animalTypes.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 = animalTypes[index - 1];
                var m = t.GetMethod("Voice");
                var o = Activator.CreateInstance(t);
                m.Invoke(o, new object[] {
   
   
    times });
            }
        }
    }
}

Lib程序实例:

using System;

namespace Animals.Lib
{
   
   
   
    public class Cat
    {
   
   
   
        public void Voice(int times) {
   
   
   
            for (int i = 0; i < times; i++) {
   
   
   
                Console.WriteLine("Meow!");
            }
        }
    }
}

using System;

namespace Animals.Lib
{
   
   
   
    public class Sheep
    {
   
   
   
        public void Voice(int times)
        {
   
   
   
            for (int i = 0; i < times; i++)
            {
   
   
   
                Console.WriteLine("Meye!");
            }
        }
    }
}

using System;

namespace Animals.Lib2
{
   
   
   
    public class Cow
    {
   
   
   
        public void Voice(int times)
        {
   
   
   
            for (int i = 0; i < times; i++)
            {
   
   
   
                Console.WriteLine("Moon!");
            }
        }
    }
}

using System;

namespace Animals.Lib2
{
   
   
   
    public class Dog
    {
   
   
   
        public void Voice(int times)
        {
   
   
   
            for (int i = 0; i < times; i++)
            {
   
   
   
                Console.WriteLine("Woof!");
            }
        }
    }
}

采用接口
TBD.

本文同步分享在 博客“doublepeng-Qian”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部
返回顶部
顶部