抽象类:
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();
}
}
}
如上所示,您应该根据您的需要和约束选择两个可能的选项。
ActivatorUtilities.CreateInstance
:这个方法每次创建一个新的实例,不查询目标类型的服务集合。如果您事先不知道所有可能的目标类型(或者出于某种原因不想注册它们),这是很方便的。ActivatorUtilities.GetServiceOrCreateInstance
:该方法在服务集合中查找目标类型;如果找到一个注册,它返回相应的实例,否则它的行为像ActivatorUtilities.CreateInstance
。这意味着您可以像往常一样在服务集合中为每个类型注册目标类型,并使用最合适的生命周期(单例、作用域或瞬态)。这种方法的唯一缺点是,如果你有一些单例或限定作用域的目标类型,你必须提供一种在服务集合中注册它们的方法,这在类似插件的应用程序中可能会很棘手。
再一次,请注意在Rater
子类型中没有关于哪些依赖可以被注入的约束,因为毕竟所有的"肮脏";依赖解析的工作是由ActivatorUtilities
类完成的。