如何在使用反射创建实例时传递记录器对象?



抽象类:

public abstract class Rater
{
public Rater()
{
}
public abstract decimal Rate(Policy policy);
}

儿童类:

public class AutoPolicyRater : Rater
{
public readonly ILogger<AutoPolicyRater> _logger;

public AutoPolicyRater(ILogger<AutoPolicyRater> logger)
{ 
_logger = logger;
}
public override decimal Rate(Policy policy)
{
_logger.Log("Rating AUTO policy...");
_logger.Log("Validating policy.");
if (String.IsNullOrEmpty(policy.Make))
{
_logger.Log("Auto policy must specify Make");
return 0m;
}
if (policy.Make == "BMW")
{
if (policy.Deductible < 500)
{

return 1000m;
}
return 900m;
}
return 0m;
}
}
public class LandPolicyRater : Rater
{
public readonly ILogger<LandPolicyRater> _logger;

public AutoPolicyRater(ILogger<LandPolicyRater> logger)
{ 
_logger = logger;
}
public override decimal Rate(Policy policy)
{
_logger.Log("Rating LAND policy...");
_logger.Log("Validating policy.");
if (policy.BondAmount == 0 || policy.Valuation == 0)
{
_logger.Log("Land policy must specify Bond Amount and Valuation.");
return 0m;
}
if (policy.BondAmount < 0.8m * policy.Valuation)
{
_logger.Log("Insufficient bond amount.");
return 0m;
}
return (policy.BondAmount * 0.05m);
}
}

工厂类,我想在其中动态传递记录器对象:

public class RaterFactory
{
private readonly IRatingUpdater _ratingUpdater;

public RaterFactory(ILogger logger)
{

}
public Rater Create(Policy policy)
{
try
{
return (Rater)Activator.CreateInstance(
Type.GetType($"MyCompany.{policy.Type}PolicyRater"),
new object[] { ?? });//here I want to pass logger object
}
catch
{
return new UnknownPolicyRater();
}
}
}

由于这些类不是控制器,并且我想在工厂方法中创建对象,我如何将记录器对象和日志信息传递给应用程序洞察力?我想传递通用的记录器对象,但是,如果有另一种方法来实现,我可以。

编辑:

在@fildor的建议之后,我在下面尝试了一下,它正在记录应用程序洞察跟踪中的信息。

public class RaterFactory
{
private readonly ILoggerFactory _loggerFactory;
public RaterFactory(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
public Rater Create(Policy policy)
{
try
{
string typeString = $"MyCompany.{policy.Type}PolicyRater";
ILogger modelLogger = _loggerFactory.CreateLogger(typeString);
return (Rater)Activator.CreateInstance(
Type.GetType($"MyCompany.{policy.Type}PolicyRater"),
new object[] { modelLogger });
}
catch
{
return new UnknownPolicyRater();
}
}
}
public class AutoPolicyRater : Rater
{
public readonly ILogger _logger;

public AutoPolicyRater(ILogger logger)
{ 
_logger = logger;
}
//other code
}

按要求:一个可能的实现:

public class RaterFactory
{
private readonly ILoggerFactory _loggerFactory;
public RaterFactory(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
}
public Rater Create(Policy policy)
{
try
{
return (Rater)Activator.CreateInstance(
Type.GetType($"MyCompany.{policy.Type}PolicyRater"),
new object[] { _loggerFactory });
}
catch
{
return new UnknownPolicyRater();
}
}
}

然后…

public class AutoPolicyRater : Rater
{
private readonly ILogger<AutoPolicyRater> _logger;

public AutoPolicyRater(ILoggerFactory loggerFactory)
{ 
_logger = loggerFactory.CreateLogger<AutoPolicyRater>();
}
public override decimal Rate(Policy policy)
{
// ... ommited for brevity
}
}

RaterFactory类不需要预先知道所有注入到它创建的实例中的依赖项。

相反,您可以注入IServiceProvider,并让ActivatorUtilities解决每次创建的Rater实例的依赖关系。

可以这样做:

public class RaterFactory
{
private readonly IServiceProvider _serviceProvider;
public RaterFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public Rater Create(Policy policy)
{
try
{
// OPTION 1
return (Rater)ActivatorUtilities.CreateInstance(
_serviceProvider,
Type.GetType($"MyCompany.{policy.Type}PolicyRater"));
// OPTION 2
return (Rater)ActivatorUtilities.GetServiceOrCreateInstance(
_serviceProvider,
Type.GetType($"MyCompany.{policy.Type}PolicyRater"));
}
catch
{
return new UnknownPolicyRater();
}
}
}

如上所示,您应该根据您的需要和约束选择两个可能的选项。

  1. ActivatorUtilities.CreateInstance:这个方法每次创建一个新的实例,不查询目标类型的服务集合。如果您事先不知道所有可能的目标类型(或者出于某种原因不想注册它们),这是很方便的。
  2. ActivatorUtilities.GetServiceOrCreateInstance:该方法在服务集合中查找目标类型;如果找到一个注册,它返回相应的实例,否则它的行为像ActivatorUtilities.CreateInstance。这意味着您可以像往常一样在服务集合中为每个类型注册目标类型,并使用最合适的生命周期(单例、作用域或瞬态)。这种方法的唯一缺点是,如果你有一些单例或限定作用域的目标类型,你必须提供一种在服务集合中注册它们的方法,这在类似插件的应用程序中可能会很棘手。

再一次,请注意在Rater子类型中没有关于哪些依赖可以被注入的约束,因为毕竟所有的"肮脏";依赖解析的工作是由ActivatorUtilities类完成的。

最新更新