Kc_*_*Kc_ 5 c# ioc-container factory-method autofac interceptor
我似乎无法在 Autofac 中解决这种情况:
所以我试图为 IFinal 创建一个工厂,但我似乎无法得到正确的解决方案。
示例代码:
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Dependency>().As<IDependency>();
builder.RegisterType<Final>().As<IFinal>();
// this fails because context c is not available at the time finalObjectFactoryMethod is used
builder.Register<Factory>((c,p)=>{
var dependency = c.Resolve<IDependency>();
Func<int, IFinal> finalObjectFactoryMethod =
rta => c.Resolve<IFinal>(
new TypedParameter(typeof(IDependency), dependency),
new TypedParameter(typeof(int), rta)
);
return new Factory(finalObjectFactoryMethod);
}).As<IFactory>();
// this works but doesn't use the resolve mechanism for IFinal
/*
builder.Register<Factory>((c,p)=>{
var dependency = c.Resolve<IDependency>();
Func<int, IFinal> finalObjectFactoryMethod = rta => new Final(dependency, rta);
return new Factory(finalObjectFactoryMethod);
}).As<IFactory>();
*/
IContainer container = builder.Build();
IFactory factory = container.Resolve<IFactory>();
IFinal final = factory.GetFinalObject(42);
}
}
public interface IDependency{}
public class Dependency: IDependency{}
public interface IFinal
{
void Test();
}
public class Final: IFinal
{
public Final(IDependency dependency, int runtimeArgument){}
public void Test(){}
}
public interface IFactory
{
IFinal GetFinalObject(int runtimeArgument);
}
public class Factory: IFactory
{
readonly Func<int, IFinal> _finalObjectFactoryMethod;
public Factory(Func<int, IFinal> finalObjectFactoryMethod)
{
_finalObjectFactoryMethod = finalObjectFactoryMethod;
}
public IFinal GetFinalObject(int runtimeArgument)
{
return _finalObjectFactoryMethod(runtimeArgument);
}
}
Run Code Online (Sandbox Code Playgroud)
Google 和 Autofac 文档对此无能为力。
不知怎的,我的脑子里似乎有一个结,也许我只是尝试使用错误的模式。
我很确定有一个解决方案,但我找不到它。
您必须将工厂 添加delegate
到Final
:
public class Final : IFinal
{
public delegate IFinal Factory(int runtimeArgument);
public Final(IDependency dependency, int runtimeArgument) { }
public void Test() { }
}
Run Code Online (Sandbox Code Playgroud)
Autofac 足够聪明,可以填充其他参数,因此您的工厂委托只能具有您在运行时指定的参数,而其他参数则由魔法解析。
然后你注册类型:
builder
.RegisterType<Final>()
.As<IFinal>();
Run Code Online (Sandbox Code Playgroud)
这是完整的示例:
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder
.RegisterType<Dependency>()
.As<IDependency>();
builder
.RegisterType<Final>()
.As<IFinal>();
using(var container = builder.Build())
using (var scope = container.BeginLifetimeScope())
{
var finalFactory = scope.Resolve<Final.Factory>();
IFinal final = finalFactory(42);
}
}
Run Code Online (Sandbox Code Playgroud)
你根本不需要这Factory
门课。委托可以直接从scope
任何其他依赖项解析或以与任何其他依赖项相同的方式使用,并由 Autofac 注入。只是Final.Factory
作为你的依赖。
该文档在委托工厂中描述了此技术
“提出正确的问题,你就会找到正确的答案”的一个很好的例子。
我已经尝试让它工作 2 天了,在我在这里发布问题后 1 小时,我自己找到了答案:P
这是包括拦截器的工作代码:
class MainClass
{
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Interceptor>();
builder.RegisterType<Dependency>().As<IDependency>();
builder.RegisterType<Final>().As<IFinal>();
builder.Register<IFinal>((c, p) =>
{
IDependency dependency = c.Resolve<IDependency>();
int runtimeArgument = p.Named<int>("runtimeArgument");
return new Final(dependency, runtimeArgument);
}).As<IFinal>()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(Interceptor));
builder.Register<Factory>((c,p)=>{
Factory.FactoryMethod finalObjectFactoryMethod = c.Resolve<Factory.FactoryMethod>();
return new Factory(finalObjectFactoryMethod);
}).As<IFactory>()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(Interceptor));
IContainer container = builder.Build();
IFactory factory = container.Resolve<IFactory>();
IFinal final = factory.GetFinalObject(42);
final.Test();
}
}
public interface IDependency{}
public class Dependency: IDependency{}
public interface IFinal
{
void Test();
}
public class Final: IFinal
{
public Final(IDependency dependency, int runtimeArgument){}
public void Test(){}
}
public interface IFactory
{
IFinal GetFinalObject(int runtimeArgument);
}
public class Factory: IFactory
{
public delegate IFinal FactoryMethod(int runtimeArgument);
readonly FactoryMethod _finalObjectFactoryMethod;
public Factory(FactoryMethod finalObjectFactoryMethod)
{
_finalObjectFactoryMethod = finalObjectFactoryMethod;
}
public IFinal GetFinalObject(int runtimeArgument)
{
return _finalObjectFactoryMethod(runtimeArgument);
}
}
public class Interceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine($"call {invocation.Method.Name}");
invocation.Proceed();
Console.WriteLine($"return from {invocation.Method.Name}");
}
}
Run Code Online (Sandbox Code Playgroud)
拦截器现在将其写入控制台:
call GetFinalObject
return from GetFinalObject
call Test
return from Test
Run Code Online (Sandbox Code Playgroud)
也许这可以帮助其他人。
归档时间: |
|
查看次数: |
3643 次 |
最近记录: |