如何在使用反射创建实例时传递记录器 object?
How to pass logger object while creating instance using reflection?
摘要Class:
public abstract class Rater
{
public Rater()
{
}
public abstract decimal Rate(Policy policy);
}
Child classes:
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);
}
}
工厂class,我想动态传递记录器的地方object:
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();
}
}
}
由于这些 class 不是控制器,我想在我的工厂方法中创建 object,我如何将记录器 object 和日志信息传递给 application insight?我想通过通用记录器object,但是,如果有另一种方法可以实现,我没问题。
编辑:
根据@fildor 的建议,我在下面进行了尝试,它正在 Application Insight 跟踪中记录信息。
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
class 不需要事先知道注入到它创建的实例中的所有依赖项。
相反,您可以注入 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
:该方法在服务集合中查找目标类型;如果找到注册,则它 returns 对应的实例,否则它的行为类似于 ActivatorUtilities.CreateInstance
。这意味着您可以像往常一样在服务集合中注册目标类型,并为每种类型设置最合适的生命周期(单例、作用域或瞬态)。这种方法的唯一缺点是,如果您有一些单例或作用域目标类型,您必须提供一种方法将它们注册到服务集合中,这在 plugin-like 应用程序中可能很棘手。
再次请注意,在 Rater
子类型中可以注入哪些依赖项没有任何限制,因为毕竟依赖项解析的“脏”工作是由 ActivatorUtilities
class.
摘要Class:
public abstract class Rater
{
public Rater()
{
}
public abstract decimal Rate(Policy policy);
}
Child classes:
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);
}
}
工厂class,我想动态传递记录器的地方object:
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();
}
}
}
由于这些 class 不是控制器,我想在我的工厂方法中创建 object,我如何将记录器 object 和日志信息传递给 application insight?我想通过通用记录器object,但是,如果有另一种方法可以实现,我没问题。
编辑:
根据@fildor 的建议,我在下面进行了尝试,它正在 Application Insight 跟踪中记录信息。
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
class 不需要事先知道注入到它创建的实例中的所有依赖项。
相反,您可以注入 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
:该方法在服务集合中查找目标类型;如果找到注册,则它 returns 对应的实例,否则它的行为类似于ActivatorUtilities.CreateInstance
。这意味着您可以像往常一样在服务集合中注册目标类型,并为每种类型设置最合适的生命周期(单例、作用域或瞬态)。这种方法的唯一缺点是,如果您有一些单例或作用域目标类型,您必须提供一种方法将它们注册到服务集合中,这在 plugin-like 应用程序中可能很棘手。
再次请注意,在 Rater
子类型中可以注入哪些依赖项没有任何限制,因为毕竟依赖项解析的“脏”工作是由 ActivatorUtilities
class.