gpt4 book ai didi

c# - 如何使用被解析的类型来解析依赖

转载 作者:太空狗 更新时间:2023-10-29 19:42:26 25 4
gpt4 key购买 nike

我有几个依赖类型为 ILogger 的类. ILogger的执行需要知道它是记录器的类型,即 ILogger对于 Foo将是 new Logger(typeof(Foo)) , 对于 Bar它将是new Logger(typeof(Bar))

我希望 Unity 自动注入(inject)适当的记录器;换句话说,当我调用 container.Resolve<Foo>() , 我想要一个 new Logger(typeof(Foo))注入(inject) Foo实例。

如何在 Unity 中进行设置?有没有办法将正在解析的类型传递给依赖项?

(在我的真实代码中,我实际上有一个 ILoggerFactory 和一个 Create 方法,它也将类型作为参数。所以我可以将工厂传递给我的类,它们会调用 Create自己获得合适的记录器,但它不像我想要实现的那样优雅)


一些让事情更清晰的代码:

interface ILogger
{
...
}

class Logger : ILogger
{
private readonly Type _type;
public Logger(Type type)
{
_type = type;
}
...
}

class Foo
{
private readonly ILogger _logger;
public Foo(ILogger logger) // here I want a Logger with its type set to Foo
{
_logger = logger;
}
}

related question显示了我正在尝试做的事情,并且接受的答案正是我正在寻找的东西......但它适用于 NInject,而不是 Unity。

最佳答案

这是一个容器扩展,它将 Logger 构造函数的 Type 参数设置为 ILogger 注入(inject)的类型。

transient IBuilderContext.Policies 用于存储 ILogger 注入(inject)的类型。

也许它比需要的更复杂,但这似乎可行

public class LoggerExtension : UnityContainerExtension
{
public static NamedTypeBuildKey LoggerBuildKey = new NamedTypeBuildKey<Logger>();

protected override void Initialize()
{
Context.Strategies.Add(new LoggerTrackingPolicy(), UnityBuildStage.TypeMapping);
Context.Strategies.Add(new LoggerBuildUpStrategy(), UnityBuildStage.PreCreation);
}
}

public class LoggerTrackingPolicy : BuilderStrategy
{
public LoggerTrackingPolicy()
{
}

public override void PreBuildUp(IBuilderContext context)
{
if (context.BuildKey.Type != typeof(Logger))
{
var loggerPolicy = context.Policies.Get<ILoggerPolicy>(LoggerExtension.LoggerBuildKey);
if (loggerPolicy == null)
{
loggerPolicy = new LoggerPolicy();
context.Policies.Set<ILoggerPolicy>(loggerPolicy, LoggerExtension.LoggerBuildKey);
}

loggerPolicy.Push(context.BuildKey.Type);
}
}
}

public class LoggerBuildUpStrategy : BuilderStrategy
{
public LoggerBuildUpStrategy()
{
}

public override void PreBuildUp(IBuilderContext context)
{
if (context.BuildKey.Type == typeof(Logger))
{
var policy = context.Policies.Get<ILoggerPolicy>(LoggerExtension.LoggerBuildKey);
Type type = policy.Peek();
if (type != null)
{
context.AddResolverOverrides(new ParameterOverride("type", new InjectionParameter(typeof(Type), type)));
}
}
}

public override void PostBuildUp(IBuilderContext context)
{
if (context.BuildKey.Type != typeof(Logger))
{
var policy = context.Policies.Get<ILoggerPolicy>(LoggerExtension.LoggerBuildKey);
policy.Pop();
}
}
}

public interface ILoggerPolicy : IBuilderPolicy
{
void Push(Type type);
Type Pop();
Type Peek();
}

public class LoggerPolicy : ILoggerPolicy
{
private Stack<Type> types = new Stack<Type>();

public void Push(Type type)
{
types.Push(type);
}

public Type Peek()
{
if (types.Count > 0)
{
return types.Peek();
}

return null;
}

public Type Pop()
{
if (types.Count > 0)
{
return types.Pop();
}

return null;
}
}

它的工作原理是:当尝试解析不是 Logger 的类型时,在 TypeMapping 阶段(在任何创建之前),该类型被压入堆栈。稍后,在创建之前,如果类型是 Logger,那么它被注入(inject)的类型将从堆栈中窥视,并且该类型用作解析器覆盖。创建后,如果类型不是 Logger,则从堆栈中弹出。

还有一些代码来确保它正常工作(我向记录器添加了一个 Type 属性只是为了验证它是否设置正确):

class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();

container.RegisterType<ILogger, Logger>();
container.AddNewExtension<LoggerExtension>();

var a = container.Resolve<A>();
var b = container.Resolve<B>();
var c = container.Resolve<C>();
var d = container.Resolve<D>();
var x = container.Resolve<X>();
}
}

public interface ILogger
{
Type Type { get; }
}

public class Logger : ILogger
{
private readonly Type _type;
public Logger(Type type)
{
_type = type;
}

public Type Type { get { return _type; } }
}

public class A
{
public A(ILogger logger)
{
System.Diagnostics.Debug.Assert(logger.Type == typeof(A));
}
}

public class B
{
public B(ILogger logger)
{
System.Diagnostics.Debug.Assert(logger.Type == typeof(B));
}
}

public class C
{
public C(A a, D d, B b, ILogger logger)
{
System.Diagnostics.Debug.Assert(logger.Type == typeof(C));
}
}

public class D
{
public D()
{
}
}

public class X
{
public X(Y y)
{
}
}

public class Y
{
public Y(ILogger logger)
{
System.Diagnostics.Debug.Assert(logger.Type == typeof(Y));
}
}

关于c# - 如何使用被解析的类型来解析依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35297344/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com