PRISM 与使用类型解析的工厂解析接口
PRISM resolve interface with factory that uses type to resolve
我一直在用 PRISM 构建一个应用程序,这个应用程序在未来几年会不断发展,所以它是模块化的,并且考虑到了 IoC。
在这个应用程序中,我目前正在为日志记录机制实现 Nlog。
因为我不想在整个应用程序中添加对 NLog 的引用,所以我为记录器创建了一个接口
public interface ILog
{
void Log(LogLevel loglevel, string format);
void Log(LogLevel loglevel, string format, params object[] args);
void Log(LogLevel loglevel, Exception exc, string format, params object[] args);
}
我也为工厂创建了一个接口
public interface ILogFactory
{
ILog Initialize(Type type);
}
工厂采用类型参数,可用于创建特定于 class 的记录器。现在是我要使用 ILog 的挑战,我希望有一个使用目标类型 class.
的实例
public class ClassA
{
private ILog Logger { get; set;}
public ClassA(Ilog logger)
{
Logger = logger;
}
}
如何将我的 ILogFactory 连接到 PRISM,以便解决使用 Ilog 的 class,即使用 ILogFactory.Initialize(Type 类型),在本例中为 typeof(ClassA)。
所以在搜索了更多网络之后,我终于找到了我要找的东西
this blog
我不得不修改代码以使其不依赖于 log4net 这导致了以下代码
一个 BuildTrackingExtension,我们需要知道我们要在哪里创建记录器。
public class BuildTrackingExtension : UnityContainerExtension
{
protected override void Initialize()
{
Context.Strategies.AddNew<BuildTrackingStrategy>(UnityBuildStage.TypeMapping);
}
public static IBuildTrackingPolicy GetPolicy(IBuilderContext context)
{
return context.Policies.Get<IBuildTrackingPolicy>(context.BuildKey, true);
}
public static IBuildTrackingPolicy SetPolicy(IBuilderContext context)
{
IBuildTrackingPolicy policy = new BuildTrackingPolicy();
context.Policies.SetDefault(policy);
return policy;
}
}
public class BuildTrackingStrategy : BuilderStrategy
{
public override void PreBuildUp(IBuilderContext context)
{
var policy = BuildTrackingExtension.GetPolicy(context)
?? BuildTrackingExtension.SetPolicy(context);
policy.BuildKeys.Push(context.BuildKey);
}
public override void PostBuildUp(IBuilderContext context)
{
IBuildTrackingPolicy policy = BuildTrackingExtension.GetPolicy(context);
if ((policy != null) && (policy.BuildKeys.Count > 0))
{
policy.BuildKeys.Pop();
}
}
}
public interface IBuildTrackingPolicy : IBuilderPolicy
{
Stack<object> BuildKeys { get; }
}
public class BuildTrackingPolicy : IBuildTrackingPolicy
{
public BuildTrackingPolicy()
{
BuildKeys = new Stack<object>();
}
public Stack<object> BuildKeys { get; private set; }
}
然后使用 LogCreationExtension 从我的 ILogFactory 创建记录器
public class LogCreationExtension : UnityContainerExtension
{
private ILogFactory LogFactory;
private LogCreationStrategy strategy;
public LogCreationExtension(ILogFactory logFactory)
{
LogFactory = logFactory;
}
protected override void Initialize()
{
strategy = new LogCreationStrategy(LogFactory);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
}
public class LogCreationStrategy : BuilderStrategy
{
public bool IsPolicySet { get; private set; }
private ILogFactory LogFactory;
public LogCreationStrategy(ILogFactory logFactory)
{
LogFactory = logFactory;
}
public override void PreBuildUp(IBuilderContext context)
{
Type typeToBuild = context.BuildKey.Type;
if (typeof(ILog).Equals(typeToBuild))
{
if (context.Policies.Get<IBuildPlanPolicy>(context.BuildKey) == null)
{
Type typeForLog = LogCreationStrategy.GetLogType(context);
IBuildPlanPolicy policy = new LogBuildPlanPolicy(typeForLog, LogFactory);
context.Policies.Set<IBuildPlanPolicy>(policy, context.BuildKey);
IsPolicySet = true;
}
}
}
public override void PostBuildUp(IBuilderContext context)
{
if (IsPolicySet)
{
context.Policies.Clear<IBuildPlanPolicy>(context.BuildKey);
IsPolicySet = false;
}
}
private static Type GetLogType(IBuilderContext context)
{
Type logType = null;
IBuildTrackingPolicy buildTrackingPolicy = BuildTrackingExtension.GetPolicy(context);
if ((buildTrackingPolicy != null) && (buildTrackingPolicy.BuildKeys.Count >= 2))
{
logType = ((NamedTypeBuildKey)buildTrackingPolicy.BuildKeys.ElementAt(1)).Type;
}
else
{
StackTrace stackTrace = new StackTrace();
//first two are in the log creation strategy, can skip over them
for (int i = 2; i < stackTrace.FrameCount; i++)
{
StackFrame frame = stackTrace.GetFrame(i);
logType = frame.GetMethod().DeclaringType;
if (!logType.FullName.StartsWith("Microsoft.Practices"))
{
break;
}
}
}
return logType;
}
}
public class LogBuildPlanPolicy : IBuildPlanPolicy
{
private ILogFactory LogFactory;
public LogBuildPlanPolicy(Type logType, ILogFactory logFactory)
{
LogType = logType;
LogFactory = logFactory;
}
public Type LogType { get; private set; }
public void BuildUp(IBuilderContext context)
{
if (context.Existing == null)
{
ILog log = LogFactory.Initialize(LogType);
context.Existing = log;
}
}
}
使用 unity 连接它
//Container.RegisterType<ILogFactory, NLogLogFactory>();
Container.RegisterInstance<ILogFactory>(_LogFactory);
Container.AddNewExtension<BuildTrackingExtension>();
Container.AddNewExtension<LogCreationExtension>();
我正在使用 RegisterInstance,因为我在调用 InitializeShell 之前使用了 logfactory
我一直在用 PRISM 构建一个应用程序,这个应用程序在未来几年会不断发展,所以它是模块化的,并且考虑到了 IoC。 在这个应用程序中,我目前正在为日志记录机制实现 Nlog。
因为我不想在整个应用程序中添加对 NLog 的引用,所以我为记录器创建了一个接口
public interface ILog
{
void Log(LogLevel loglevel, string format);
void Log(LogLevel loglevel, string format, params object[] args);
void Log(LogLevel loglevel, Exception exc, string format, params object[] args);
}
我也为工厂创建了一个接口
public interface ILogFactory
{
ILog Initialize(Type type);
}
工厂采用类型参数,可用于创建特定于 class 的记录器。现在是我要使用 ILog 的挑战,我希望有一个使用目标类型 class.
的实例public class ClassA
{
private ILog Logger { get; set;}
public ClassA(Ilog logger)
{
Logger = logger;
}
}
如何将我的 ILogFactory 连接到 PRISM,以便解决使用 Ilog 的 class,即使用 ILogFactory.Initialize(Type 类型),在本例中为 typeof(ClassA)。
所以在搜索了更多网络之后,我终于找到了我要找的东西 this blog
我不得不修改代码以使其不依赖于 log4net 这导致了以下代码
一个 BuildTrackingExtension,我们需要知道我们要在哪里创建记录器。
public class BuildTrackingExtension : UnityContainerExtension
{
protected override void Initialize()
{
Context.Strategies.AddNew<BuildTrackingStrategy>(UnityBuildStage.TypeMapping);
}
public static IBuildTrackingPolicy GetPolicy(IBuilderContext context)
{
return context.Policies.Get<IBuildTrackingPolicy>(context.BuildKey, true);
}
public static IBuildTrackingPolicy SetPolicy(IBuilderContext context)
{
IBuildTrackingPolicy policy = new BuildTrackingPolicy();
context.Policies.SetDefault(policy);
return policy;
}
}
public class BuildTrackingStrategy : BuilderStrategy
{
public override void PreBuildUp(IBuilderContext context)
{
var policy = BuildTrackingExtension.GetPolicy(context)
?? BuildTrackingExtension.SetPolicy(context);
policy.BuildKeys.Push(context.BuildKey);
}
public override void PostBuildUp(IBuilderContext context)
{
IBuildTrackingPolicy policy = BuildTrackingExtension.GetPolicy(context);
if ((policy != null) && (policy.BuildKeys.Count > 0))
{
policy.BuildKeys.Pop();
}
}
}
public interface IBuildTrackingPolicy : IBuilderPolicy
{
Stack<object> BuildKeys { get; }
}
public class BuildTrackingPolicy : IBuildTrackingPolicy
{
public BuildTrackingPolicy()
{
BuildKeys = new Stack<object>();
}
public Stack<object> BuildKeys { get; private set; }
}
然后使用 LogCreationExtension 从我的 ILogFactory 创建记录器
public class LogCreationExtension : UnityContainerExtension
{
private ILogFactory LogFactory;
private LogCreationStrategy strategy;
public LogCreationExtension(ILogFactory logFactory)
{
LogFactory = logFactory;
}
protected override void Initialize()
{
strategy = new LogCreationStrategy(LogFactory);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
}
public class LogCreationStrategy : BuilderStrategy
{
public bool IsPolicySet { get; private set; }
private ILogFactory LogFactory;
public LogCreationStrategy(ILogFactory logFactory)
{
LogFactory = logFactory;
}
public override void PreBuildUp(IBuilderContext context)
{
Type typeToBuild = context.BuildKey.Type;
if (typeof(ILog).Equals(typeToBuild))
{
if (context.Policies.Get<IBuildPlanPolicy>(context.BuildKey) == null)
{
Type typeForLog = LogCreationStrategy.GetLogType(context);
IBuildPlanPolicy policy = new LogBuildPlanPolicy(typeForLog, LogFactory);
context.Policies.Set<IBuildPlanPolicy>(policy, context.BuildKey);
IsPolicySet = true;
}
}
}
public override void PostBuildUp(IBuilderContext context)
{
if (IsPolicySet)
{
context.Policies.Clear<IBuildPlanPolicy>(context.BuildKey);
IsPolicySet = false;
}
}
private static Type GetLogType(IBuilderContext context)
{
Type logType = null;
IBuildTrackingPolicy buildTrackingPolicy = BuildTrackingExtension.GetPolicy(context);
if ((buildTrackingPolicy != null) && (buildTrackingPolicy.BuildKeys.Count >= 2))
{
logType = ((NamedTypeBuildKey)buildTrackingPolicy.BuildKeys.ElementAt(1)).Type;
}
else
{
StackTrace stackTrace = new StackTrace();
//first two are in the log creation strategy, can skip over them
for (int i = 2; i < stackTrace.FrameCount; i++)
{
StackFrame frame = stackTrace.GetFrame(i);
logType = frame.GetMethod().DeclaringType;
if (!logType.FullName.StartsWith("Microsoft.Practices"))
{
break;
}
}
}
return logType;
}
}
public class LogBuildPlanPolicy : IBuildPlanPolicy
{
private ILogFactory LogFactory;
public LogBuildPlanPolicy(Type logType, ILogFactory logFactory)
{
LogType = logType;
LogFactory = logFactory;
}
public Type LogType { get; private set; }
public void BuildUp(IBuilderContext context)
{
if (context.Existing == null)
{
ILog log = LogFactory.Initialize(LogType);
context.Existing = log;
}
}
}
使用 unity 连接它
//Container.RegisterType<ILogFactory, NLogLogFactory>();
Container.RegisterInstance<ILogFactory>(_LogFactory);
Container.AddNewExtension<BuildTrackingExtension>();
Container.AddNewExtension<LogCreationExtension>();
我正在使用 RegisterInstance,因为我在调用 InitializeShell 之前使用了 logfactory