• 手把手教你写DI_2_小白徒手撸构造函数注入


    小白徒手撸构造函数注入

    在上一节:手把手教你写DI_1_DI框架有什么?

    我们已经知道我们要撸哪些东西了

    那么我们开始动工吧,这里呢,我们找小白同学来表演下

    小白同学 :我们先定义一下我们的广告招聘纸有什么:

    public abstract class ServiceDefintion  // 小白同学 :我们换个名字,不叫 ServiceDescriptor ,撸也要撸出自己的标志嘛
    {
        public abstract Type ServiceType { get; }
        public abstract Type ImplementationType { get; }
        public abstract Lifetime Lifetime { get; }
    }
    
    public enum Lifetime  // 小白同学 :定义一下要支持的三种生命周期
    {
        Singleton,
        Scoped,
        Transient
    }
    
    // 小白同学 :搞个集合存放他们
    public interface IServiceDefintions : IEnumerable<ServiceDefintion>
    {
        void Add(ServiceDefintion serviceDefintion);
    }
    
    public class ServiceDefintions : IServiceDefintions
    {
        private readonly List<ServiceDefintion> services = new List<ServiceDefintion>();
    
        public void Add(ServiceDefintion serviceDefintion)
        {
            if (serviceDefintion == null)
            {
                throw new ArgumentNullException(nameof(serviceDefintion));
            }
            services.Add(serviceDefintion);
        }
    }
    

    好,我们实现两种不同的广告类型

    public class TypeServiceDefintion : ServiceDefintion  // 小白同学 :这种是只提供类型的,怎么建立实例需要我们解析生成,但是对使用DI的人来说,很方便,不用管怎么去new
    {
        public override Type ServiceType { get; }
        public override Type ImplementationType { get; }
        public override Lifetime Lifetime { get; }
    
        public TypeServiceDefintion(Type serviceType, Type implementationType, Lifetime lifetime)
        {
            ServiceType = serviceType;
            ImplementationType = implementationType;
            Lifetime = lifetime;
        }
    }
    
    public interface IImplementationFactory
    {
        Func<INamedServiceProvider, object> ImplementationFactory { get; }
    }
    
    public class DelegateServiceDefintion : ServiceDefintion, IImplementationFactory  // 小白同学 :这种是用户自己new对象,少数特殊情况,用户会自己写特殊逻辑,所以我们需要提供支持
    {
        public DelegateServiceDefintion(Type serviceType, Type implementationType, Lifetime lifetime,
            Func<IServiceProvider, object> implementationFactory)
        {
            ServiceType = serviceType;
            ImplementationType = implementationType;
            Lifetime = lifetime;
            ImplementationFactory = implementationFactory;
        }
    
        public override Type ServiceType { get; }
    
        public override Type ImplementationType { get; }
    
        public override Lifetime Lifetime { get; }
    
        public Func<IServiceProvider, object> ImplementationFactory { get; }
    }
    

    小白同学 :好了,我们有服务定义描述了,来创建IServiceProvider

    public class ServiceProvider : IServiceProvider
    {
        private readonly IServiceDefintions services;
    
        public ServiceProvider(IServiceDefintions services)
        {
            this.services = services;
        }
        public object GetService(Type serviceType)
        {
            var defintion = TryGetDefintion(serviceType); // 小白同学 :查找一下服务定义
            if (defintion != null)
            {
                switch (defintion.Lifetime)
                {
                    case Lifetime.Singleton:
                        return null;  // 小白同学 :啥?怎么处理?emm 后面说吧,脑容量不够啦
    
                    case Lifetime.Scoped:
                        return null;  // 小白同学 :啥?怎么处理?emm 后面说吧,脑容量不够啦
    
                    case Lifetime.Transient:
                        if(defintion is DelegateServiceDefintion defi)
                        {
                            return defi.ImplementationFactory(this);
                            // 小白同学 :haha, 不用我们做,真简单
                        }
                        else // 小白同学 :TypeServiceDefintion
                        {
                            // 小白同学 :啥?怎么处理?emm 后面说吧,脑容量不够啦
                        }
    
                    default:
                        return null;
                }
            }
            else
            {
                return null;
            }
        }
    
        private ServiceDefintion TryGetDefintion(Type serviceType)
        {
            return services.FirstOrDefault(i => i.ServiceType == serviceType);  //大神: what ? 每次都遍历一下?太low了吧?
        }
    
    }
    

    小白同学 :捂脸.gif 我们居然每次都遍历,简直太笨了,赶紧改下,免得大神吐槽

    public class ServiceProvider : IServiceProvider
    {
        private readonly Dictionary<Type, ServiceDefintion> services;
    
        public ServiceProvider(IServiceDefintions services)
        {
            this.services = services.ToDictionary(i => i.ServiceType);  
            //大神: what 1 ? 有相同的 ServiceType 怎么办? 
        }
    
        private ServiceDefintion TryGetDefintion(Type serviceType)  //大神: what 2 ? 这个方法怎么这么怪
        {
            services.TryGetValue(serviceType, out var defintion);  
            return defintion;
        }
    
        ...
    }
    

    小白同学 :又被吐槽了,再改下

    public class ServiceProvider : IServiceProvider
    {
        private readonly Dictionary<Type, ServiceDefintion[]> services;  
        //大神: 呵呵,你就这样写吧,我打赌100块你后面肯定要改
        //小白同学: ......
    
        public ServiceProvider(IServiceDefintions services)
        {
            this.services = services.GroupBy(i => i.ServiceType).ToDictionary(i => i.Key, i => i.ToArray());
        }
    
        private ServiceDefintion TryGetDefintion(Type serviceType) 
        {
            return services.TryGetValue(serviceType, out var defintion) ? defintion.LastOrDefault() : null;
        }
    
        ...
    }
    

    小白同学: 好了,我们简单测试一下

    [Fact]
    public void Test()
    {
        var a = new ServiceDefintions();
        a.Add(new DelegateServiceDefintion(typeof(TransientTest),typeof(TransientTest),Lifetime.Transient,i => this));
        var service = new ServiceProvider(a);
    
        var result0 = service.GetService(typeof(TransientTest));
        Assert.Same(this, result0);
    }
    // 大神: 你用this 去测瞬态?你确定this是瞬态的func 每次都会调用?
    // 小白同学: 我。。。。。。我改
    
    [Fact]
    public void Test()
    {
        var a = new ServiceDefintions();
        a.Add(new DelegateServiceDefintion(typeof(TransientTest),typeof(TransientTest),Lifetime.Transient,i => new TransientTest()));
        var service = new ServiceProvider(a);
    
        var result0 = service.GetService(typeof(TransientTest));
        var result1 = service.GetService(typeof(TransientTest));
        Assert.NotNull(result0);
        Assert.NotNull(result1);
        Assert.NotSame(result0, result1);
    }
    

    小白同学: 我们来做TypeServiceDefintion 解析支持

    public class ServiceProvider : IServiceProvider
    {
        public object GetService(Type serviceType)
        {
            ...
    
            case Lifetime.Transient:
                if(defintion is DelegateServiceDefintion defi)
                {
                    return defi.ImplementationFactory(this);
                }
                else
                {
                    var d = defintion as TypeServiceDefintion;
                    var constructor = d.ImplementationType.GetConstructors().FirstOrDefault(i => i.IsPublic); // 小白同学:  反射获取构造函数
                    var ps = constructor.GetParameters();
                    var args = new object[ps.Length];
                    for (int j = 0; j < ps.Length; j++)
                    {
                        var p = ps[j];
                        args[j] = i.GetService(p.ParameterType);  // 小白同学:  获取参数值
                    }
                    return constructor.Invoke(args);  // 小白同学:  创建;
                }
    
            ....
        }
    }
    

    小白同学: 你看我写的不错吧

    大神:呵呵,这样反射性能你考虑了吗? 泛型你考虑了吗? 还有你每次都重新生成DelegateServiceDefintion?

    小白同学: 我知道反射该用IL或者表达式树处理,但观众不好看嘛

    大神:呵呵,你不会写吧,你看看人家lemon大神怎么写的 - file

    小白同学: 好,我下来学习。 泛型不过是再动态生成一下类型嘛,这样就行啦

    public class ServiceProvider : IServiceProvider
    {
        public object GetService(Type serviceType)
        {
            ...
    
            case Lifetime.Transient:
                if(defintion is DelegateServiceDefintion defi)
                {
                    return defi.ImplementationFactory(this);
                }
                else
                {
                    var d = defintion as TypeServiceDefintion;
                    var implementationType = serviceType.IsConstructedGenericType 
                        ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments)
                        : d.ImplementationType;
                    var constructor = implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic); // 小白同学:  反射获取构造函数
                    .....
                }
    
            ....
        }
    }
    

    小白同学: 哦,还有缓存:

    public class ServiceProvider : IServiceProvider
    {
        private readonly Dictionary<Type, ConstructorInfo> cache = new Dictionary<Type, ConstructorInfo>();
    
        public object GetService(Type serviceType)
        {
            ...
    
            case Lifetime.Transient:
                if(defintion is DelegateServiceDefintion defi)
                {
                    return defi.ImplementationFactory(this);
                }
                else
                {
                    ConstructorInfo constructor = null;
                    if(cache.ContainsKey(serviceType))
                    {
                        constructor = cache[serviceType];
                    }
                    else 
                    {
                        var d = defintion as TypeServiceDefintion;
                        var implementationType = serviceType.IsConstructedGenericType 
                            ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments)
                            : d.ImplementationType;
                        constructor = cache[serviceType] = implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic); // 小白同学:  反射获取构造函数
                    }
                    ....
                }
    
            ....
        }
    }
    

    大神: .......我想自闭..... 你都不考虑多线程吗?

    小白同学: !!! 我,我,我,我换成它 ConcurrentDictionary<Type, ConstructorInfo> cache

    大神:算你NB,SingletonScoped 你打算怎么做?

    小白同学: 简单, copy 一下

    public class ServiceProvider : IServiceProvider
    {
        private readonly ConcurrentDictionary<Type, ConstructorInfo> cache = new ConcurrentDictionary<Type, ConstructorInfo>();
    
        public object GetService(Type serviceType)
        {
            case Lifetime.Singleton:
                    if(defintion is DelegateServiceDefintion defi)
                    {
                        return defi.ImplementationFactory(this);
                    }
                    else
                    {
                        ConstructorInfo constructor = cache.GetOrAdd(serviceType, i => 
                        {
                            var d = defintion as TypeServiceDefintion;
                            var implementationType = serviceType.IsConstructedGenericType 
                                ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments)
                                : d.ImplementationType;
                            return implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic);
                        });
                        ar ps = constructor.GetParameters();
                        var args = new object[ps.Length];
                        for (int j = 0; j < ps.Length; j++)
                        {
                            var p = ps[j];
                            args[j] = i.GetService(p.ParameterType);  // 小白同学:  获取参数值
                        }
                        return constructor.Invoke(args);  // 小白同学:  创建;
                    }
    
            case Lifetime.Scoped:
                    if(defintion is DelegateServiceDefintion defi)
                    {
                        return defi.ImplementationFactory(this);
                    }
                    else
                    {
                        ConstructorInfo constructor = cache.GetOrAdd(serviceType, i => 
                        {
                            var d = defintion as TypeServiceDefintion;
                            var implementationType = serviceType.IsConstructedGenericType 
                                ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments)
                                : d.ImplementationType;
                            return implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic);
                        });
                        ar ps = constructor.GetParameters();
                        var args = new object[ps.Length];
                        for (int j = 0; j < ps.Length; j++)
                        {
                            var p = ps[j];
                            args[j] = i.GetService(p.ParameterType);  // 小白同学:  获取参数值
                        }
                        return constructor.Invoke(args);  // 小白同学:  创建;
                    }
    
            case Lifetime.Transient:
                if(defintion is DelegateServiceDefintion defi)
                {
                    return defi.ImplementationFactory(this);
                }
                else
                {
                    ConstructorInfo constructor = cache.GetOrAdd(serviceType, i => 
                    {
                        var d = defintion as TypeServiceDefintion;
                        var implementationType = serviceType.IsConstructedGenericType 
                            ? d.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments)
                            : d.ImplementationType;
                        return implementationType.GetConstructors().FirstOrDefault(i => i.IsPublic);
                    });
                    ar ps = constructor.GetParameters();
                    var args = new object[ps.Length];
                    for (int j = 0; j < ps.Length; j++)
                    {
                        var p = ps[j];
                        args[j] = i.GetService(p.ParameterType);  // 小白同学:  获取参数值
                    }
                    return constructor.Invoke(args);  // 小白同学:  创建;
                }
    
            ....
        }
    }
    

    大神:我!!!!!!!!!! 我给你一刀!!!!!!!

    小白同学: 啊!!!!!!!!!

    由于小白同学受伤,本次节目中断,等小白同学养好伤,我们再继续

    下一章 小白徒手支持 SingletonScoped 生命周期

  • 相关阅读:
    GCD
    Android仿人人客户端(v5.7.1)——对从服务器端(网络)获取的图片进行本地双缓存处理(编码实现)
    systimestamp
    byte数组之间的赋值,byte和TCHAR数组的赋值
    如何修改hotspot默认信道
    Wifi的密码长度有何限制
    微信心跳机制
    如何内置iperf到手机中
    如何adb shell进入ctia模式
    本周推荐10款免费的网站模板设计
  • 原文地址:https://www.cnblogs.com/fs7744/p/9926523.html
Copyright © 2020-2023  润新知