![](/img/trans.png)
[英]Autofac. RegisterType after .Build and register/resolve list
[英]Different behavior of Autofac depending of usage of builder.Register or builder.RegisterType
使用特定的(复杂)类嵌套,当我尝试解析向其注册的类型时,在运行时在Autofac中遇到异常
builder.RegisterType<ClassThatDoesNotWork>().UsingConstructor(expression);
但是相同的注册适用于:
builder.Register<ClassThatDoesNotWork>(func);
添加.As<MyType>
似乎没有任何改变。
我不知道是PEBKAC还是bug。 另外,我发现> builder.RegisterType<T>().UsingConstructor(expression);
在其他情况下工作。
我做了一个完整的工作示例(抱歉,它有点长,但是如果我使用过于简单的结构,问题就消失了):
class Program
{
static void Main(string[] args)
{
var a = InjectionConfig.ResolveNamed<WhateverService>("MyServiceType1");
//var b = InjectionConfig.ResolveNamed<WhateverService>("MyServiceType2");
var c = InjectionConfig.Resolve<RandomInnerClass>();
var e = InjectionConfig.Resolve<ClassThatWorks>();
// This one will fail
var f = InjectionConfig.Resolve<ClassThatDoesNotWork>();
}
}
public static class InjectionConfig
{
private static IContainer Container { get; }
static InjectionConfig()
{
var builder = new ContainerBuilder();
builder.RegisterModule<InitModule>();
Container = builder.Build();
}
public static TService Resolve<TService>()
{
return Container.Resolve<TService>();
}
public static TService ResolveNamed<TService>(string dependancy)
{
return Container.ResolveNamed<TService>(dependancy);
}
}
public class InitModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
RegisterTemplateServices(builder);
RegisterPropertiesGenerationServices(builder);
}
private void RegisterTemplateServices(ContainerBuilder builder)
{
var myServiceType1 = new WhateverService("MyServiceType1");
builder.RegisterInstance(myServiceType1).Keyed<WhateverService>("MyServiceType1").SingleInstance();
//var myServiceType2 = new WhateverService("MyServiceType2");
//builder.RegisterInstance(myServiceType2).Keyed<WhateverService>("MyServiceType2").SingleInstance();
}
private void RegisterPropertiesGenerationServices(ContainerBuilder builder)
{
Func<IComponentContext, RandomInnerClass> funCtorRandomInnerClass =
context => new RandomInnerClass(InjectionConfig.ResolveNamed<WhateverService>("MyServiceType1"));
builder.Register<RandomInnerClass>(funCtorRandomInnerClass).As<RandomInnerClass>();
// This kind of initialization works
Func<IComponentContext, ClassThatWorks> funcWorks = context => new ClassThatWorks(new AnotherClass(InjectionConfig.Resolve<RandomInnerClass>()), InjectionConfig.ResolveNamed<WhateverService>("MyServiceType1"));
builder.Register<ClassThatWorks>(funcWorks);
// This one FAILS at runtime
Expression<Func<ClassThatDoesNotWork>> expressionDoesNotWork = () => new ClassThatDoesNotWork(new AnotherClass(InjectionConfig.Resolve<RandomInnerClass>()), InjectionConfig.ResolveNamed<WhateverService>("MyServiceType1"));
builder.RegisterType<ClassThatDoesNotWork>().UsingConstructor(expressionDoesNotWork);
// It would work if instead for registration I used :
// Func<IComponentContext, ClassThatDoesNotWork> funcExample = context => new ClassThatDoesNotWork(new AnotherClass(InjectionConfig.Resolve<RandomInnerClass>()), InjectionConfig.ResolveNamed<WhateverService>("MyServiceType1"));
//builder.Register<ClassThatDoesNotWork>(funcExample);
}
}
internal class AnotherClass
{
public AnotherClass(RandomInnerClass resolve) { }
}
internal class ClassThatDoesNotWork
{
public ClassThatDoesNotWork(AnotherClass a, WhateverService b) { }
}
internal class ClassThatWorks
{
public ClassThatWorks(AnotherClass a, WhateverService b) { }
}
internal class RandomInnerClass
{
public RandomInnerClass(WhateverService a) { }
}
internal class WhateverService
{
public WhateverService(string myIdentifier) { }
}
例外:
Autofac.Core.DependencyResolutionException:激活特定注册期间发生错误。 有关详细信息,请参见内部异常。 注册:激活程序= ClassThatDoesNotWork(ReflectionActivator),服务= [ConsoleApp1.ClassThatDoesNotWork],生命周期= Autofac.Core.Lifetime.CurrentScopeLifetime,共享=无,所有权= OwnedByLifetimeScope --->在'Autofac.Core.Activators中找不到的构造函数可以使用可用的服务和参数调用类型为'ConsoleApp1.ClassThatDoesNotWork'的.Reflection.DefaultConstructorFinder:无法解析构造函数'Void .ctor(ConsoleApp1.AnotherClass,ConsoleApp1.WhateverService)'的参数'ConsoleApp1.AnotherClass a'。 (有关详细信息,请参阅内部异常。)---> Autofac.Core.DependencyResolutionException:不能使用可用服务调用类型为'ConsoleApp1.ClassThatDoesNotWork'的'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'的构造函数。参数:无法解析构造函数'Void .ctor(ConsoleApp1.AnotherClass,ConsoleApp1.WhateverService)'的参数'ConsoleApp1.AnotherClass a'。 àAutofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(IComponentContext上下文,IEnumerable
1 parameters) à Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable
1个参数)àAutofac.Core.Activate.InstanceLookup.Activate (IEnumerable1 parameters) --- Fin de la trace de la pile d'exception interne --- à Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable
1参数)àAutofac.Core.Resolving.InstanceLookup.Execute()à Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope,IComponentRegistration注册,IEnumerable1 parameters) à Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable
1参数)àAutofac.Core.Lifetime(LifeTimeILifetimeScope.Re注册,IEnumerable1 parameters) à Autofac.Core.Container.ResolveComponent(IComponentRegistration registration, IEnumerable
1 parameters) à Autofac.Core.Container.ResolveComponent(IComponentRegistration registration, IEnumerable
1参数)àAutofac.ResolutionExtensions.TryResolveService(IComponentContext上下文,服务服务,IEnumerable1 parameters, Object& instance) à Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable
1参数)àAutofac.ResolutionExtensions.Resolve [ TService](IComponentContext上下文,IEnumerable`1参数)àAutofac.ResolutionExtensions.Resolve [TService](IComponentContext上下文)àConsoleApp1.InjectionConfig.ResolveTService dans T:\\ Temp \\ ConsoleApp1 \\ Program.cs:ligne 55àConsoleApp1.Program.Main (String [] args)dans T:\\ Temp \\ ConsoleApp1 \\ Program.cs:ligne 27
如您在中间看到的那样,使用
Func<IComponentContext, ClassThatDoesNotWork> funcExample = context => new ClassThatDoesNotWork(new AnotherClass(InjectionConfig.Resolve<RandomInnerClass>()), InjectionConfig.ResolveNamed<WhateverService>("MyServiceType1"));
builder.Register<ClassThatDoesNotWork>(funcExample);
代替
Expression<Func<ClassThatDoesNotWork>> expressionDoesNotWork = () => new ClassThatDoesNotWork(new AnotherClass(InjectionConfig.Resolve<RandomInnerClass>()), InjectionConfig.ResolveNamed<WhateverService>("MyServiceType1"));
builder.RegisterType<ClassThatDoesNotWork>().UsingConstructor(expressionDoesNotWork);
解决问题。 对我来说,两个构造都应该做相同的事情,但是不应该。
我在.Net 4.6.2中使用了autofac 4.8.1(last)。
我想知道我是否做错了什么,另外,这两种构造之间最好的是什么(出于性能方面的考虑)。 谢谢
首先,您注册组件的方式看起来没有什么充分的理由过于复杂。 有了这堆new WhateverClass()
您似乎正在为它做Autofac的工作,特别是考虑到Autofac抱怨您做的不完全正确。 我认为这可以简单得多。
但是,即使我们对此加以区分,您的代码也会遇到更严重的问题。 使用静态InjectionConfig
解决注册中的所有内容,您实际上在打破Autofac的生命周期范围管理。 这正是使用Autofac时不应该执行的操作。 如果您需要解决注册lambda中的问题,则应使用Autofac提供的IComponentContext。
所以,我要做的是下面。 如果由于某种原因该方法不起作用,那么让我们查找一下。
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterModule<InitModule>();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var a = scope.ResolveNamed<WhateverService>("MyServiceType1");
var c = scope.Resolve<RandomInnerClass>();
var e = scope.Resolve<ClassThatWorks>();
// This one now works
var f = scope.Resolve<ClassThatDoesNotWork>();
}
}
}
public class InitModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
RegisterTemplateServices(builder);
RegisterPropertiesGenerationServices(builder);
}
private void RegisterTemplateServices(ContainerBuilder builder)
{
builder.RegisterType<WhateverService>()
.WithParameter(new NamedParameter("myIdentifier", "MyServiceType1"))
.Named<WhateverService>("MyServiceType1")
.AsSelf()
.SingleInstance();
//var myServiceType2 = new WhateverService("MyServiceType2");
//builder.RegisterInstance(myServiceType2).Keyed<WhateverService>("MyServiceType2").SingleInstance();
}
private void RegisterPropertiesGenerationServices(ContainerBuilder builder)
{
builder.RegisterType<AnotherClass>().AsSelf().InstancePerLifetimeScope();
builder.RegisterType<RandomInnerClass>().AsSelf().InstancePerLifetimeScope();
builder.RegisterType<ClassThatWorks>().AsSelf().InstancePerLifetimeScope();
builder.RegisterType<ClassThatDoesNotWork>().AsSelf().InstancePerLifetimeScope();
}
}
internal class AnotherClass
{
public AnotherClass(RandomInnerClass resolve)
{
}
}
internal class ClassThatDoesNotWork
{
public ClassThatDoesNotWork(AnotherClass a, [KeyFilter("MyServiceType1")] WhateverService b)
{
}
}
internal class ClassThatWorks
{
public ClassThatWorks(AnotherClass a, [KeyFilter("MyServiceType1")] WhateverService b)
{
}
}
internal class RandomInnerClass
{
public RandomInnerClass([KeyFilter("MyServiceType1")] WhateverService a)
{
}
}
internal class WhateverService
{
public WhateverService(string myIdentifier)
{
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.