簡體   English   中英

Autofac:注冊通用抽象 class

[英]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調用僅注冊基本類型為BaseAPIwndArbolVM<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM