PRISM解析与使用类型解析的工厂的接口

时间:2016-12-07 09:37:41

标签: c# prism

我一直在使用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);
}

工厂采用Type参数,该参数可用于创建特定于该类的记录器。现在迎来挑战,我将使用ILog我希望有一个使用目标类型类的实例。

public class ClassA
{
    private ILog Logger { get; set;}
    public ClassA(Ilog logger)
    {
        Logger = logger;
    }
}

如何将我的ILogFactory连接到PRISM,以便解决使用Ilog的类,该类使用ILogFactory.Initialize(Type type),在本例中为typeof(ClassA)。

1 个答案:

答案 0 :(得分:0)

所以在搜索了更多的网页后,我终于找到了我想要的东西 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;
        }
    }
}

使用统一布线

        //Container.RegisterType<ILogFactory, NLogLogFactory>();
        Container.RegisterInstance<ILogFactory>(_LogFactory);
        Container.AddNewExtension<BuildTrackingExtension>();
        Container.AddNewExtension<LogCreationExtension>();

我正在使用RegisterInstance,因为我在调用InitializeShell之前使用了logfactory