我在API中有一个类,有一个静态方法,用于验证和记录详细信息。任何指导如何注入ILogger接口。
public class ValidateDataInAPI
{
public static bool IsValid(string data)
{
//do something
If(error)
{
_logger.Error("Log error as implemented by caller");
}
}
}
答案 0 :(得分:12)
如果我理解正确,您希望将ILogger的实例注入静态方法。正如您可能已经想到的那样,当依赖方法是静态的时,您无法使用依赖注入“正常方式”。
您在这里寻找的是service locator pattern。
使用StructureMap IoC容器(但你真的可以使用任何容器),用于连接它的配置可能如下所示:
For<ILogger>().Use<SomeLoggerImplementation>();
实施后,您的调用代码可能如下所示:
public class ValidateDataInAPI
{
private static ILogger Logger
{
// DependencyResolver could be any DI container here.
get { return DependencyResolver.Resolve<ILogger>(); }
}
public static bool IsValid(string data)
{
//do something
If(error)
{
Logger.Error("Log error as implemented by caller");
}
}
}
我想指出,这可以被视为一种反模式,只应在有明确理由的情况下使用,而不仅仅是为了方便。
依赖注入的整个想法是你将依赖关系注入到调用代码的构造函数中,从而将所有类的依赖关系暴露给外部世界。
这不仅提高了代码的可读性(没有内部隐藏的“惊喜”),还提高了可测试性。您不希望在单元测试项目中配置IoC容器,对吗?使用依赖注入以正确的方式消除了这种必要性,并且当您想要对代码进行单元测试时,可以使您的生活变得更加轻松。
如果您不熟悉依赖注入的概念,this link可以帮助您入门。那里有很多信息。
使用依赖注入,您的调用代码将如下所示:
public class ValidateDataInAPI : IValidateDataInAPI
{
private readonly ILogger _logger;
// Since the dependency on ILogger is now exposed through the class's constructor
// you can easily create a unit test for this class and inject a mock of ILogger.
// You will not need to configure your DI container to be able to unit test.
public ValidateDataInAPI(ILogger logger)
{
_logger = logger;
}
public bool IsValid(string data)
{
//do something
If(error)
{
_logger.Error("Log error as implemented by caller");
}
}
}
同样,通过为验证类定义接口,您可以将该验证类注入API类:
public interface IValidateDataInAPI
{
bool IsValid(string data);
}
您现在可以模拟Validator类,它可以让您更轻松地对API类进行单元测试。
话虽如此,如果你确实需要保持你的IsValid方法是静态的,那么服务定位器模式可能就是这样。