[英]Autofac: register generic abstract class
我正在使用 Autofac 6.0.0 版本,但在尝试注册以下通用抽象 class 时遇到了麻烦:
public abstract class wndArbolVM<TGrupo, TNodoGrupo, THoja, TNodoHoja> : ViewModelBase
where TGrupo : class, IIdEntero, IPadreId, new()
where THoja : class,IIdEntero, IGrupoId, new()
where TNodoGrupo : TreeItemHierarchicalVM, new()
where TNodoHoja : TreeItemLeafVM, new()
{
}
我曾尝试在许多 forms 中注册此错误,其中最常见的是“类型 wndArbolVM`4[TGrupo,TNodoGrupo,THoja,TNodoHoja] 是通用类型定义”
编辑:这是我尝试注册的方式(我在更新到 6.0.0 之前使用的是 Autofac 3.5.0 版,它就像一个魅力):
var builder = new ContainerBuilder();
Assembly[] ensamblados =
{
Assembly.GetExecutingAssembly(),
Assembly.GetAssembly(typeof(Configurator)),
Assembly.GetAssembly(typeof(BaseAPI)),
Assembly.GetCallingAssembly()
};
builder.RegisterAssemblyTypes(ensamblados).Where(p => p.BaseType == typeof(BaseAPI)).SingleInstance();
builder.RegisterByAttributes(ensamblados);
builder.RegisterType<wndPrincipal>().SingleInstance();
builder.RegisterType<Sesion>().SingleInstance();
builder.RegisterInstance(LogManager.GetCurrentClassLogger()).As<ILogger>();
builder.RegisterInstance(new Entorno(Entorno.GESTION)).As<Entorno>();
builder.RegisterInstance(this).As<App>();
Container = builder.Build();
Edit2:完整的堆栈跟踪
en System.Dynamic.Utils.TypeUtils.ValidateType(Type type)
en System.Linq.Expressions.Expression.New(ConstructorInfo constructor, IEnumerable`1 arguments)
en Autofac.Core.Activators.Reflection.ConstructorBinder.GetConstructorInvoker(ConstructorInfo constructorInfo)
en System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
en Autofac.Core.Activators.Reflection.ConstructorBinder..ctor(ConstructorInfo constructorInfo)
en Autofac.Core.Activators.Reflection.ReflectionActivator.ConfigurePipeline(IComponentRegistryServices componentRegistryServices, IResolvePipelineBuilder pipelineBuilder)
en Autofac.Core.Registration.ComponentRegistration.BuildResolvePipeline(IComponentRegistryServices registryServices, IResolvePipelineBuilder pipelineBuilder)
en Autofac.Core.Registration.ComponentRegistration.BuildResolvePipeline(IComponentRegistryServices registryServices)
en Autofac.Core.Registration.ComponentRegistryBuilder.Build()
en Autofac.ContainerBuilder.Build(ContainerBuildOptions options)
en App.Application_Startup(Object sender, StartupEventArgs e) en
en System.Windows.Application.OnStartup(StartupEventArgs e)
en System.Windows.Application.<.ctor>b__1_0(Object unused)
en System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
en System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
任何帮助,将不胜感激
这里不足以实际解决问题 - 没有实际的堆栈跟踪,没有显示您如何尝试注册事物的代码等。
但是,您无法注册抽象 class ,因为您无法创建抽象 class 的实例。 Autofac 所做的一切——基本上——为你调用new
。 如果你考虑一下,你不能这样做:
var x = new wndArbolVM<TGrupo, TNodoGrupo, THoja, TNodoHoja>();
你不能“新建”一个抽象的 class。 这就是 DI 所做的一切——它会为您调用所有正确的构造函数。
现在,您可以将具体的 class 注册为抽象 class,这确实有效。 假设你有这个:
public class DerivedViewModel : wndArbolVM<A, B, C, D>
{
// contents here
}
现在您有了一个可以注册的具体 class。
var builder = new ContainerBuilder();
builder.RegisterType<DerivedViewModel>()
.As<wndArbolVM<A, B, C, D>>();
var container = builder.Build();
// This should work:
using var scope = container.BeginLifetimeScope();
var model = scope.Resolve<wndArbolVM<A, B, C, D>>();
// model will be a DerivedViewModel
但是,同样,由于您无法创建抽象 class 的实例,这将不起作用:
var builder = new ContainerBuilder();
// This will never work. You can't create instances
// of an abstract class. The thing in RegisterType<T>
// is what will (basically) be used in
// new T();
// and you can't do
// new wndArbolVM<TGrupo, TNodoGrupo, THoja, TNodoHoja>();
// even if you used concrete type parameters like
// new wndArbolVM<A, B, C, D>();
builder.RegisterType<wndArbolVM<TGrupo, TNodoGrupo, THoja, TNodoHoja>>();
问题已于 2020 年 12 月 4 日更新,以添加更多注册信息。
显示的新注册信息未显示wndArbolVM<TGrupo, TNodoGrupo, THoja, TNodoHoja>
类型的任何实际使用情况。 带有堆栈跟踪的实际完整异常,以指示异常发生的位置仍未包含在问题中,因此很难确定问题发生的位置。 该异常将是解决此问题的关键——不仅是消息,还有堆栈跟踪。
至于问题的更新:
RegisterAssemblyTypes
调用仅注册基本类型为BaseAPI
但wndArbolVM<TGrupo, TNodoGrupo, THoja, TNodoHoja>
是ViewModelBase
的东西,我必须假设它不在其中。RegisterByAttributes
方法不是 Autofac 附带的,所以我不知道它的作用; 而且我没有看到wndArbolVM<TGrupo, TNodoGrupo, THoja, TNodoHoja>
class 的任何属性,所以我无法猜测。但是,我确实注意到您使用的是 Autofac 3.5.0 并直接使用 Autofac 6。自 2014 年 6 月发布 Autofac 3.5.0 以来,发生了很多变化。 每个主要版本(4.x、5.x、6.x)都表示重大更改,而不仅仅是新功能。 我们已尽最大努力保持兼容性,但不能保证 100%,您需要在代码中考虑到这一点。
如果是我遇到这种情况,我会放慢速度并尝试在单元测试中重现它。 例如,也许有一个单元测试只注册一个wndArbolVM<TGrupo, TNodoGrupo, THoja, TNodoHoja>
实例并解析它。 不是所有其他的东西,装配扫描和一切,但只是......一件事。 或者,只有那一件事和非常少量的其他东西,可能只是足够的存根对象来使事情正常工作。 一旦我让它工作......现在比较。 我的有效测试代码和我更复杂的真实系统有什么不同?
从那里开始遍历代码并定位问题。 也许使用单元测试作为一个单独尝试的地方。 与其注册存根,不如逐一切换以开始注册“真实事物”。 弄清楚它什么时候破裂。 这将为您指明一个可以查看真实、更复杂系统的地方。
不幸的是,这就是我在这里所能提供的。 看起来您设置了一个非常复杂的系统,并且在缺乏信息和跨三个主要版本的 Autofac 升级之间,需要发生的很多事情都是特定于应用程序的。 尽管我愿意提供帮助,但我真的没有太多额外的时间来迭代问题更新/答案更新周期。 希望这里的内容可以解除您的障碍,让您走上解决问题的道路。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.