动手造轮子:实现一个简单的依赖注入(一)

动手造轮子:实现一个简单的依赖注入(一)

Intro

在上一篇文章中主要介绍了一下要做的依赖注入的整体设计和大概编程体验,这篇文章要开始写代码了,开始实现自己的依赖注入框架。

类图

首先来温习一下上次提到的类图

服务生命周期

服务生命周期定义:

public enum ServiceLifetime : sbyte
{
    /// <summary>
    /// Specifies that a single instance of the service will be created.
    /// </summary>
    Singleton = 0,

    /// <summary>
    /// Specifies that a new instance of the service will be created for each scope.
    /// </summary>
    Scoped = 1,

    /// <summary>
    /// Specifies that a new instance of the service will be created every time it is requested.
    /// </summary>
    Transient = 2,
}

服务定义

服务注册定义:

public class ServiceDefinition
{
    // 服务生命周期
    public ServiceLifetime ServiceLifetime { get; }
    // 实现类型
    public Type ImplementType { get; }
    // 服务类型
    public Type ServiceType { get; }
    // 实现实例
    public object ImplementationInstance { get; }
    // 实现工厂
    public Func<IServiceProvider, object> ImplementationFactory { get; }

    // 获取真实的实现类型
    public Type GetImplementType()
    {
        if (ImplementationInstance != null)
            return ImplementationInstance.GetType();

        if (ImplementationFactory != null)
            return ImplementationFactory.Method.DeclaringType;

        if (ImplementType != null)
            return ImplementType;

        return ServiceType;
    }

    public ServiceDefinition(object instance, Type serviceType)
    {
        ImplementationInstance = instance;
        ServiceType = serviceType;
        ServiceLifetime = ServiceLifetime.Singleton;
    }

    public ServiceDefinition(Type serviceType, ServiceLifetime serviceLifetime) : this(serviceType, serviceType, serviceLifetime)
    {
    }

    public ServiceDefinition(Type serviceType, Type implementType, ServiceLifetime serviceLifetime)
    {
        ServiceType = serviceType;
        ImplementType = implementType ?? serviceType;
        ServiceLifetime = serviceLifetime;
    }

    public ServiceDefinition(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetime serviceLifetime)
    {
        ServiceType = serviceType;
        ImplementationFactory = factory;
        ServiceLifetime = serviceLifetime;
    }
}

为了使用起来更方便添加了一些静态方法

public static ServiceDefinition Singleton<TService>(Func<IServiceProvider, object> factory)
{
    return new ServiceDefinition(typeof(TService), factory, ServiceLifetime.Singleton);
}

public static ServiceDefinition Scoped<TService>(Func<IServiceProvider, object> factory)
{
    return new ServiceDefinition(typeof(TService), factory, ServiceLifetime.Scoped);
}

public static ServiceDefinition Transient<TService>(Func<IServiceProvider, object> factory)
{
    return new ServiceDefinition(typeof(TService), factory, ServiceLifetime.Transient);
}

public static ServiceDefinition Singleton<TService>()
{
    return new ServiceDefinition(typeof(TService), ServiceLifetime.Singleton);
}

public static ServiceDefinition Scoped<TService>()
{
    return new ServiceDefinition(typeof(TService), ServiceLifetime.Scoped);
}

public static ServiceDefinition Transient<TService>()
{
    return new ServiceDefinition(typeof(TService), ServiceLifetime.Transient);
}

public static ServiceDefinition Singleton<TService, TServiceImplement>() where TServiceImplement : TService
{
    return new ServiceDefinition(typeof(TService), typeof(TServiceImplement), ServiceLifetime.Singleton);
}

public static ServiceDefinition Scoped<TService, TServiceImplement>() where TServiceImplement : TService
{
    return new ServiceDefinition(typeof(TService), typeof(TServiceImplement), ServiceLifetime.Scoped);
}

public static ServiceDefinition Transient<TService, TServiceImplement>() where TServiceImplement : TService
{
    return new ServiceDefinition(typeof(TService), typeof(TServiceImplement), ServiceLifetime.Transient);
}

ServiceContainer

serviceContainer v1

public class ServiceContainer : IServiceContainer
{
    internal readonly List<ServiceDefinition> _services;

    private readonly ConcurrentDictionary<Type, object> _singletonInstances;

    private readonly ConcurrentDictionary<Type, object> _scopedInstances;

    private readonly List<object> _transientDisposables = new List<object>();

    private readonly bool _isRootScope;

    public ServiceContainer()
    {
        _isRootScope = true;
        _singletonInstances = new ConcurrentDictionary<Type, object>();
        _services = new List<ServiceDefinition>();
    }

    internal ServiceContainer(ServiceContainer serviceContainer)
    {
        _isRootScope = false;
        _singletonInstances = serviceContainer._singletonInstances;
        _services = serviceContainer._services;
        _scopedInstances = new ConcurrentDictionary<Type, object>();
    }

    public void Add(ServiceDefinition item)
    {
        _services.Add(item);
    }

    public IServiceContainer CreateScope()
    {
        return new ServiceContainer(this);
    }

    private bool _disposed;

    public void Dispose()
    {
        if (_disposed)
        {
            return;
        }

        if (_isRootScope)
        {
            lock (_singletonInstances)
            {
                if (_disposed)
                {
                    return;
                }

                _disposed = true;
                foreach (var instance in _singletonInstances.Values)
                {
                    (instance as IDisposable)?.Dispose();
                }

                foreach (var o in _transientDisposables)
                {
                    (o as IDisposable)?.Dispose();
                }
            }
        }
        else
        {
            lock (_scopedInstances)
            {
                if (_disposed)
                {
                    return;
                }

                _disposed = true;
                foreach (var instance in _scopedInstances.Values)
                {
                    (instance as IDisposable)?.Dispose();
                }

                foreach (var o in _transientDisposables)
                {
                    (o as IDisposable)?.Dispose();
                }
            }
        }
    }

    private object GetServiceInstance(Type serviceType, ServiceDefinition serviceDefinition)
    {
        if (serviceDefinition.ImplementationInstance != null)
            return serviceDefinition.ImplementationInstance;

        if (serviceDefinition.ImplementationFactory != null)
            return serviceDefinition.ImplementationFactory.Invoke(this);

        var implementType = (serviceDefinition.ImplementType ?? serviceType);

        if (implementType.IsInterface || implementType.IsAbstract)
        {
            throw new InvalidOperationException($"invalid service registered, serviceType: {serviceType.FullName}, implementType: {serviceDefinition.ImplementType}");
        }

        var ctorInfos = implementType.GetConstructors(BindingFlags.Instance | BindingFlags.Public);
        if (ctorInfos.Length == 0)
        {
            throw new InvalidOperationException($"service {serviceType.FullName} does not have any public constructors");
        }

        ConstructorInfo ctor;
        if (ctorInfos.Length == 1)
        {
            ctor = ctorInfos[0];
        }
        else
        {
            // try find best ctor
            ctor = ctorInfos
                .OrderBy(_ => _.GetParameters().Length)
                .First();
        }

        var parameters = ctor.GetParameters();
        if (parameters.Length == 0)
        {
            // TODO: cache New Func
            return Expression.Lambda<Func<object>>(Expression.New(ctor)).Compile().Invoke();
        }
        else
        {
            var ctorParams = new object[parameters.Length];
            for (var index = 0; index < parameters.Length; index++)
            {
                var parameter = parameters[index];
                var param = GetService(parameter.ParameterType);
                if (param == null && parameter.HasDefaultValue)
                {
                    param = parameter.DefaultValue;
                }

                ctorParams[index] = param;
            }
            return Expression.Lambda<Func<object>>(Expression.New(ctor, ctorParams.Select(Expression.Constant))).Compile().Invoke();
        }
    }

    public object GetService(Type serviceType)
    {
        var serviceDefinition = _services.LastOrDefault(_ => _.ServiceType == serviceType);
        if (null == serviceDefinition)
        {
            return null;
        }

        if (_isRootScope && serviceDefinition.ServiceLifetime == ServiceLifetime.Scoped)
        {
            throw new InvalidOperationException($"can not get scope service from the root scope, serviceType: {serviceType.FullName}");
        }

        if (serviceDefinition.ServiceLifetime == ServiceLifetime.Singleton)
        {
            var svc = _singletonInstances.GetOrAdd(serviceType, (t) => GetServiceInstance(t, serviceDefinition));
            return svc;
        }
        else if (serviceDefinition.ServiceLifetime == ServiceLifetime.Scoped)
        {
            var svc = _scopedInstances.GetOrAdd(serviceType, (t) => GetServiceInstance(t, serviceDefinition));
            return svc;
        }
        else
        {
            var svc = GetServiceInstance(serviceType, serviceDefinition);
            if (svc is IDisposable)
            {
                _transientDisposables.Add(svc);
            }
            return svc;
        }
    }
}

为了使得服务注册更加方便,可以写一些扩展方法来方便注册:

public static IServiceContainer AddSingleton<TService>([NotNull]this IServiceContainer serviceContainer, [NotNull]TService service)
{
    serviceContainer.Add(new ServiceDefinition(service, typeof(TService)));
    return serviceContainer;
}

public static IServiceContainer AddSingleton([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType)
{
    serviceContainer.Add(new ServiceDefinition(serviceType, ServiceLifetime.Singleton));
    return serviceContainer;
}

public static IServiceContainer AddSingleton([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType, [NotNull]Type implementType)
{
    serviceContainer.Add(new ServiceDefinition(serviceType, implementType, ServiceLifetime.Singleton));
    return serviceContainer;
}

public static IServiceContainer AddSingleton<TService>([NotNull]this IServiceContainer serviceContainer, [NotNull]Func<IServiceProvider, object> func)
{
    serviceContainer.Add(ServiceDefinition.Singleton<TService>(func));
    return serviceContainer;
}

public static IServiceContainer AddSingleton<TService>([NotNull]this IServiceContainer serviceContainer)
{
    serviceContainer.Add(ServiceDefinition.Singleton<TService>());
    return serviceContainer;
}

public static IServiceContainer AddSingleton<TService, TServiceImplement>([NotNull]this IServiceContainer serviceContainer) where TServiceImplement : TService
{
    serviceContainer.Add(ServiceDefinition.Singleton<TService, TServiceImplement>());
    return serviceContainer;
}

public static IServiceContainer AddScoped([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType)
{
    serviceContainer.Add(new ServiceDefinition(serviceType, ServiceLifetime.Scoped));
    return serviceContainer;
}

public static IServiceContainer AddScoped([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType, [NotNull]Type implementType)
{
    serviceContainer.Add(new ServiceDefinition(serviceType, implementType, ServiceLifetime.Scoped));
    return serviceContainer;
}

public static IServiceContainer AddScoped<TService>([NotNull]this IServiceContainer serviceContainer, [NotNull]Func<IServiceProvider, object> func)
{
    serviceContainer.Add(ServiceDefinition.Scoped<TService>(func));
    return serviceContainer;
}

public static IServiceContainer AddScoped<TService>([NotNull]this IServiceContainer serviceContainer)
{
    serviceContainer.Add(ServiceDefinition.Scoped<TService>());
    return serviceContainer;
}

public static IServiceContainer AddScoped<TService, TServiceImplement>([NotNull]this IServiceContainer serviceContainer) where TServiceImplement : TService
{
    serviceContainer.Add(ServiceDefinition.Scoped<TService, TServiceImplement>());
    return serviceContainer;
}

public static IServiceContainer AddTransient([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType)
{
    serviceContainer.Add(new ServiceDefinition(serviceType, ServiceLifetime.Transient));
    return serviceContainer;
}

public static IServiceContainer AddTransient([NotNull]this IServiceContainer serviceContainer, [NotNull]Type serviceType, [NotNull]Type implementType)
{
    serviceContainer.Add(new ServiceDefinition(serviceType, implementType, ServiceLifetime.Transient));
    return serviceContainer;
}

public static IServiceContainer AddTransient<TService>([NotNull]this IServiceContainer serviceContainer, [NotNull]Func<IServiceProvider, object> func)
{
    serviceContainer.Add(ServiceDefinition.Transient<TService>(func));
    return serviceContainer;
}

public static IServiceContainer AddTransient<TService>([NotNull]this IServiceContainer serviceContainer)
{
    serviceContainer.Add(ServiceDefinition.Transient<TService>());
    return serviceContainer;
}

public static IServiceContainer AddTransient<TService, TServiceImplement>([NotNull]this IServiceContainer serviceContainer) where TServiceImplement : TService
{
    serviceContainer.Add(ServiceDefinition.Transient<TService, TServiceImplement>());
    return serviceContainer;
}

通过上面的代码就可以实现基本依赖注入了,但是从功能上来说,上面的代码只支持获取单个服务的实例,不支持注册一个接口的多个实现,获取接口的所有实现,为此对 ServiceContainer 中的 Instance 的 ConcurrentDictionary 的 Key 进行一下改造,使得可以能够以接口类型和实现类型联合作为 key,为此就有了第二版的 ServiceContainer

ServiceContainer v2

为此定义了一个 ServiceKey 的类型,请注意这里一定要重写 GetHashCode 方法:

private class ServiceKey : IEquatable<ServiceKey>
{
    public Type ServiceType { get; }

    public Type ImplementType { get; }

    public ServiceKey(Type serviceType, ServiceDefinition definition)
    {
        ServiceType = serviceType;
        ImplementType = definition.GetImplementType();
    }

    public bool Equals(ServiceKey other)
    {
        return ServiceType == other?.ServiceType && ImplementType == other?.ImplementType;
    }

    public override bool Equals(object obj)
    {
        return Equals((ServiceKey)obj);
    }

    public override int GetHashCode()
    {
        var key = $"{ServiceType.FullName}_{ImplementType.FullName}";
        return key.GetHashCode();
    }
}

第二版的 ServiceContainer :

public class ServiceContainer : IServiceContainer
{
    internal readonly ConcurrentBag<ServiceDefinition> _services;

    private readonly ConcurrentDictionary<ServiceKey, object> _singletonInstances;

    private readonly ConcurrentDictionary<ServiceKey, object> _scopedInstances;
    private ConcurrentBag<object> _transientDisposables = new ConcurrentBag<object>();

    private class ServiceKey : IEquatable<ServiceKey>
    {
        public Type ServiceType { get; }

        public Type ImplementType { get; }

        public ServiceKey(Type serviceType, ServiceDefinition definition)
        {
            ServiceType = serviceType;
            ImplementType = definition.GetImplementType();
        }

        public bool Equals(ServiceKey other)
        {
            return ServiceType == other?.ServiceType && ImplementType == other?.ImplementType;
        }

        public override bool Equals(object obj)
        {
            return Equals((ServiceKey)obj);
        }

        public override int GetHashCode()
        {
            var key = $"{ServiceType.FullName}_{ImplementType.FullName}";
            return key.GetHashCode();
        }
    }

    private readonly bool _isRootScope;

    public ServiceContainer()
    {
        _isRootScope = true;
        _singletonInstances = new ConcurrentDictionary<ServiceKey, object>();
        _services = new ConcurrentBag<ServiceDefinition>();
    }

    private ServiceContainer(ServiceContainer serviceContainer)
    {
        _isRootScope = false;
        _singletonInstances = serviceContainer._singletonInstances;
        _services = serviceContainer._services;
        _scopedInstances = new ConcurrentDictionary<ServiceKey, object>();
    }

    public IServiceContainer Add(ServiceDefinition item)
    {
        if (_disposed)
        {
            throw new InvalidOperationException("the service container had been disposed");
        }
        if (_services.Any(_ => _.ServiceType == item.ServiceType && _.GetImplementType() == item.GetImplementType()))
        {
            return this;
        }

        _services.Add(item);
        return this;
    }

    public IServiceContainer TryAdd(ServiceDefinition item)
    {
        if (_disposed)
        {
            throw new InvalidOperationException("the service container had been disposed");
        }
        if (_services.Any(_ => _.ServiceType == item.ServiceType))
        {
            return this;
        }
        _services.Add(item);
        return this;
    }

    public IServiceContainer CreateScope()
    {
        return new ServiceContainer(this);
    }

    private bool _disposed;

    public void Dispose()
    {
        if (_disposed)
        {
            return;
        }

        if (_isRootScope)
        {
            lock (_singletonInstances)
            {
                if (_disposed)
                {
                    return;
                }

                _disposed = true;
                foreach (var instance in _singletonInstances.Values)
                {
                    (instance as IDisposable)?.Dispose();
                }

                foreach (var o in _transientDisposables)
                {
                    (o as IDisposable)?.Dispose();
                }

                _singletonInstances.Clear();
                _transientDisposables = null;
            }
        }
        else
        {
            lock (_scopedInstances)
            {
                if (_disposed)
                {
                    return;
                }

                _disposed = true;
                foreach (var instance in _scopedInstances.Values)
                {
                    (instance as IDisposable)?.Dispose();
                }

                foreach (var o in _transientDisposables)
                {
                    (o as IDisposable)?.Dispose();
                }

                _scopedInstances.Clear();
                _transientDisposables = null;
            }
        }
    }

    private object GetServiceInstance(Type serviceType, ServiceDefinition serviceDefinition)
    {
        if (serviceDefinition.ImplementationInstance != null)
            return serviceDefinition.ImplementationInstance;

        if (serviceDefinition.ImplementationFactory != null)
            return serviceDefinition.ImplementationFactory.Invoke(this);

        var implementType = (serviceDefinition.ImplementType ?? serviceType);

        if (implementType.IsInterface || implementType.IsAbstract)
        {
            throw new InvalidOperationException($"invalid service registered, serviceType: {serviceType.FullName}, implementType: {serviceDefinition.ImplementType}");
        }

        if (implementType.IsGenericType)
        {
            implementType = implementType.MakeGenericType(serviceType.GetGenericArguments());
        }

        var ctorInfos = implementType.GetConstructors(BindingFlags.Instance | BindingFlags.Public);
        if (ctorInfos.Length == 0)
        {
            throw new InvalidOperationException($"service {serviceType.FullName} does not have any public constructors");
        }

        ConstructorInfo ctor;
        if (ctorInfos.Length == 1)
        {
            ctor = ctorInfos[0];
        }
        else
        {
            // TODO: try find best ctor
            ctor = ctorInfos
                .OrderBy(_ => _.GetParameters().Length)
                .First();
        }

        var parameters = ctor.GetParameters();
        if (parameters.Length == 0)
        {
            // TODO: cache New Func
            return Expression.Lambda<Func<object>>(Expression.New(ctor)).Compile().Invoke();
        }
        else
        {
            var ctorParams = new object[parameters.Length];
            for (var index = 0; index < parameters.Length; index++)
            {
                var parameter = parameters[index];
                var param = GetService(parameter.ParameterType);
                if (param == null && parameter.HasDefaultValue)
                {
                    param = parameter.DefaultValue;
                }

                ctorParams[index] = param;
            }
            return Expression.Lambda<Func<object>>(Expression.New(ctor, ctorParams.Select(Expression.Constant))).Compile().Invoke();
        }
    }

    public object GetService(Type serviceType)
    {
        if (_disposed)
        {
            throw new InvalidOperationException($"can not get scope service from a disposed scope, serviceType: {serviceType.FullName}");
        }

        var serviceDefinition = _services.LastOrDefault(_ => _.ServiceType == serviceType);
        if (null == serviceDefinition)
        {
            if (serviceType.IsGenericType)
            {
                var genericType = serviceType.GetGenericTypeDefinition();
                serviceDefinition = _services.LastOrDefault(_ => _.ServiceType == genericType);
                if (null == serviceDefinition)
                {
                    var innerServiceType = serviceType.GetGenericArguments().First();
                    if (typeof(IEnumerable<>).MakeGenericType(innerServiceType)
                        .IsAssignableFrom(serviceType))
                    {
                        var innerRegType = innerServiceType;
                        if (innerServiceType.IsGenericType)
                        {
                            innerRegType = innerServiceType.GetGenericTypeDefinition();
                        }
                        //
                        var list = new List<object>(4);
                        foreach (var def in _services.Where(_ => _.ServiceType == innerRegType))
                        {
                            object svc;
                            if (def.ServiceLifetime == ServiceLifetime.Singleton)
                            {
                                svc = _singletonInstances.GetOrAdd(new ServiceKey(innerServiceType, def), (t) => GetServiceInstance(innerServiceType, def));
                            }
                            else if (def.ServiceLifetime == ServiceLifetime.Scoped)
                            {
                                svc = _scopedInstances.GetOrAdd(new ServiceKey(innerServiceType, def), (t) => GetServiceInstance(innerServiceType, def));
                            }
                            else
                            {
                                svc = GetServiceInstance(innerServiceType, def);
                                if (svc is IDisposable)
                                {
                                    _transientDisposables.Add(svc);
                                }
                            }
                            if (null != svc)
                            {
                                list.Add(svc);
                            }
                        }

                        var methodInfo = typeof(Enumerable)
                            .GetMethod("Cast", BindingFlags.Static | BindingFlags.Public);
                        if (methodInfo != null)
                        {
                            var genericMethod = methodInfo.MakeGenericMethod(innerServiceType);
                            var castedValue = genericMethod.Invoke(null, new object[] { list });
                            if (typeof(IEnumerable<>).MakeGenericType(innerServiceType) == serviceType)
                            {
                                return castedValue;
                            }
                            var toArrayMethod = typeof(Enumerable).GetMethod("ToArray", BindingFlags.Static | BindingFlags.Public)
                                .MakeGenericMethod(innerServiceType);

                            return toArrayMethod.Invoke(null, new object[] { castedValue });
                        }
                        return list;
                    }

                    return null;
                }
            }
            else
            {
                return null;
            }
        }

        if (_isRootScope && serviceDefinition.ServiceLifetime == ServiceLifetime.Scoped)
        {
            throw new InvalidOperationException($"can not get scope service from the root scope, serviceType: {serviceType.FullName}");
        }

        if (serviceDefinition.ServiceLifetime == ServiceLifetime.Singleton)
        {
            var svc = _singletonInstances.GetOrAdd(new ServiceKey(serviceType, serviceDefinition), (t) => GetServiceInstance(t.ServiceType, serviceDefinition));
            return svc;
        }
        else if (serviceDefinition.ServiceLifetime == ServiceLifetime.Scoped)
        {
            var svc = _scopedInstances.GetOrAdd(new ServiceKey(serviceType, serviceDefinition), (t) => GetServiceInstance(t.ServiceType, serviceDefinition));
            return svc;
        }
        else
        {
            var svc = GetServiceInstance(serviceType, serviceDefinition);
            if (svc is IDisposable)
            {
                _transientDisposables.Add(svc);
            }
            return svc;
        }
    }
}

这样我们就不仅支持了 IEnumerable<TService> 的注册,也支持 IReadOnlyList<TService>/ IReadOnlyCollection<TService> 的注册

因为 GetService 返回是 object , 不是强类型的,所以为了使用起来方便,定义了几个扩展方法,类似于微软的依赖注入框架里的 GetService<TService>()/GetServices<TService>()/GetRequiredService<TService>()

/// <summary>
/// ResolveService
/// </summary>
/// <typeparam name="TService">TService</typeparam>
/// <param name="serviceProvider">serviceProvider</param>
/// <returns></returns>
public static TService ResolveService<TService>([NotNull]this IServiceProvider serviceProvider)
    => (TService)serviceProvider.GetService(typeof(TService));

/// <summary>
/// ResolveRequiredService
/// throw exception if can not get a service instance
/// </summary>
/// <typeparam name="TService">TService</typeparam>
/// <param name="serviceProvider">serviceProvider</param>
/// <returns></returns>
public static TService ResolveRequiredService<TService>([NotNull] this IServiceProvider serviceProvider)
{
    var serviceType = typeof(TService);
    var svc = serviceProvider.GetService(serviceType);
    if (null == svc)
    {
        throw new InvalidOperationException($"service had not been registered, serviceType: {serviceType}");
    }
    return (TService)svc;
}

/// <summary>
/// Resolve services
/// </summary>
/// <typeparam name="TService">TService</typeparam>
/// <param name="serviceProvider">serviceProvider</param>
/// <returns></returns>
public static IEnumerable<TService> ResolveServices<TService>([NotNull]this IServiceProvider serviceProvider)
    => serviceProvider.ResolveService<IEnumerable<TService>>();

More

后面还更新了一版,主要优化性能,目前来说还不太满意,暂时这里先不提了

Reference

原文地址:https://www.cnblogs.com/weihanli/p/implement-dependency-injection-01.html

时间: 2024-10-11 00:58:45

动手造轮子:实现一个简单的依赖注入(一)的相关文章

如何编写一个简单的依赖注入容器

随着大规模的项目越来越多,许多项目都引入了依赖注入框架,其中最流行的有Castle Windsor, Autofac和Unity Container. 微软在最新版的Asp.Net Core中自带了依赖注入的功能,有兴趣可以查看这里. 关于什么是依赖注入容器网上已经有很多的文章介绍,这里我将重点讲述如何实现一个自己的容器,可以帮助你理解依赖注入的原理. 容器的构想 在编写容器之前,应该先想好这个容器如何使用. 容器允许注册服务和实现类型,允许从服务类型得出服务的实例,它的使用代码应该像 var

动手造轮子:实现一个简单的 EventBus

动手造轮子:实现一个简单的 EventBus Intro EventBus 是一种事件发布订阅模式,通过 EventBus 我们可以很方便的实现解耦,将事件的发起和事件的处理的很好的分隔开来,很好的实现解耦. 微软官方的示例项目 EShopOnContainers 也有在使用 EventBus . 这里的 EventBus 实现也是参考借鉴了微软 eShopOnContainers 项目. EventBus 处理流程: 微服务间使用 EventBus 实现系统间解耦: 借助 EventBus 我

简单实现依赖注入(无框架)

1.依赖注入概念 在Spring框架中,依赖注入(IOC)和面向切面编程(AOP)是它的两大核心.其中依赖注入是一个将行为从依赖中分离的技术,简单地说,它允许开发者定义一个方法函数依赖于外部其他各种交互,而不需要编码如何获得这些外部交互的实例. 这样就在各种组件之间解耦,从而获得干净的代码,相比依赖的硬编码, 一个组件只有在运行时才调用其所需要的其他组件,因此在代码运行时,通过特定的框架或容器,将其所需要的其他依赖组件进行注入,主动注入. 2.依赖注入实现       依赖注入的实现是基于反射实

简单解析依赖注入(控制反转)在Spring中的应用

IoC——Inversion of Control  控制反转DI——Dependency Injection   依赖注入 大家都知道,依赖注入是Spring中非常重要的一种设计模式.可能很多初学者对这种看起来高深的东西有一种抗拒,这里就 简单介绍一下到底什么是依赖注入,Spring到底又到底是如何运用依赖注入的. 依赖关系:在A组件中要引用B组件的对象,则称A依赖于B依赖关系会造成各组件之间的硬编码,为解决依赖关系,一般的解决方法如下: 1.A组件先创建B组件,在调用B组件方法2.A组件先通

自己动手造“轮子”---python常用的几个方法

前言:由于工作内容的原因,经常需要些python脚本,久而久之,发现有一些方法经常用到,于是就自己动手编辑了一些常用的.大众的.通用的方法.小弟不才,但也希望能为开源做做贡献. 最后再附上代码哈: 一.目前该文件中只总结了五个方法: 1.ping_network(network_ip)? ?---? ping测试的方法 2.socket_port(network_ip, port)? ---? 检测目标网络端口是否开放(正常)的方法 3.file_format_analysis(file_pat

使用Java注解实现简单的依赖注入

代码如下: /** * 注入的注解,为空,仅起标志作用 */ @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @interface Inject { } /** * 获取 bean 的容器,必通通过容器获取,而不能使用 new,因为需要使用反射获取注解信息并进行注入 */ class Container { public static <T> T getBean(Class<T> clazz) { T

再说php依赖注入

前段时间,有朋友问我yii2的依赖注入是怎么个玩法,好吧, 经常看到却一直不甚理解的概念,这里我再对自己认识的依赖注入深刻的表达下我的理解,依赖注入(DI)以及控制器反转(Ioc). 依赖注入就是组件通过构造器,方法或者属性字段来获取相应的依赖对象. 举个现实生活中的例子来理解, 比如我要一把菜刀 如何获得1.可以自己造一把,对应new一个.2.可以找生产菜刀的工厂去买一把,对应工厂模式.3.可以打电话 让店家送货上门,对应依赖注入 依赖注入(DI)的概念虽然听起来很深奥,但是如果你用过一些新兴

安卓开发 第一篇 关于依赖注入框架dagger2的使用和理解

(这篇博客真是磨难重重啊,写到一半电脑蓝屏了,还好markdown编辑器保持了部分类容) 最近开始重构项目,在重构项目中用到了依赖注入框架dagger2,发现它确实很方便,能大大加快我们编写代码的速度,同时也很方便我们对于功能模块的解耦.在这里就不过多介绍dagger2了,大家谷歌 百度一下就能得到很多关于dagger2的介绍.学习dagger2是需要一定的学习成本的,我自己开始学习的时候也差不多花了一周的时间才弄明白怎样使用dagger2,下面就说说自己对dagger2的理解和使用方法. da

Spring.NET依赖注入框架学习--简单对象注入

Spring.NET依赖注入框架学习--简单对象注入 在前面的俩篇中讲解了依赖注入的概念以及Spring.NET框架的核心模块介绍,今天就要看看怎么来使用Spring.NET实现一个简单的对象注入 常用文件 我们使用Spring.Net 框架经常要使用到的是以下文件: Common.Logging.dll  包含了Spring.Net日志方面的功能(必须) Spring.Core.dll       包含了Spring.Net 的核心库(必须) Spring.Data.dll       包含了