在软件开发中,控制反转(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)是两个非常重要的设计模式。它们的主要目的是消除代码中的依赖关系,使得代码更加灵活和可维护。IoC是一种设计原则,而DI是实现IoC的具体方法。本文将介绍如何实现一个简单的IoC容器,并展示其在实际开发中的应用。
控制反转是一种设计原则,它的核心思想是“不要调用,会调用”。这意味着在传统的编程模式中,组件之间的依赖关系是由组件自身来管理的,而在IoC模式中,这种依赖关系由外部来管理。依赖注入是实现IoC的一种方法,它通过将依赖关系注入到组件中,而不是让组件自己去寻找依赖。
IoC有三种常见的实现方式:
下面是一个简单的IoC容器的实现示例,使用C#语言编写。这个容器提供了注册和解析功能,允许开发者注册服务和接口的实现,然后在需要的地方解析出具体的实现。
public static class IoC
{
private static readonly IDictionary<Type, Type> types = new Dictionary<Type, Type>();
private static readonly IDictionary<Type, object> typeInstances = new Dictionary<Type, object>();
public static void Register<TContract, TImplementation>()
{
types[typeof(TContract)] = typeof(TImplementation);
}
public static void Register<TContract, TImplementation>(TImplementation instance)
{
typeInstances[typeof(TContract)] = instance;
}
public static T Resolve<T>()
{
return (T)Resolve(typeof(T));
}
public static object Resolve(Type contract)
{
if (typeInstances.ContainsKey(contract))
{
return typeInstances[contract];
}
else
{
Type implementation = types[contract];
ConstructorInfo constructor = implementation.GetConstructors()[0];
ParameterInfo[] constructorParameters = constructor.GetParameters();
if (constructorParameters.Length == 0)
{
return Activator.CreateInstance(implementation);
}
List<object> parameters = new List<object>(constructorParameters.Length);
foreach (ParameterInfo parameterInfo in constructorParameters)
{
parameters.Add(Resolve(parameterInfo.ParameterType));
}
return constructor.Invoke(parameters.ToArray());
}
}
}
在应用程序启动时,需要注册服务和接口的实现。然后,在需要使用服务的地方,可以通过IoC容器解析出具体的实现。
Service svc = new Service();
IoC.Register<IService, Service>(svc);
private IService currentSvc = null;
public LoginServices(IService submittedService)
{
this.currentSvc = submittedService;
}
假设有一个日志服务的接口,以及一个实现了这个接口的日志类。可以通过IoC容器来注册和解析这个服务。
public interface ILogger
{
void Log(string submittedMsg);
}
public class Logger : ILogger
{
public void Log(string submittedMsg)
{
if (!string.IsNullOrEmpty(submittedMsg))
{
Console.WriteLine(string.Format("[{0}] {1}\r\n", DateTime.Now, submittedMsg));
Console.Read();
}
}
}
public class ConsoleLogger
{
private ILogger logger = null;
public ConsoleLogger(ILogger submittedLogger)
{
this.logger = submittedLogger;
this.DisplayMessage();
}
public void DisplayMessage()
{
logger.Log("Hi..See it is working!!");
}
}
class Program
{
static void Main(string[] args)
{
IoC.Register<ILogger, Logger>();
IoC.Register<ConsoleLogger, ConsoleLogger>();
ConsoleLogger objConsoleLogger = IoC.Resolve<ConsoleLogger>();
}
}