[英]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.