Открытый универсальный тип не может быть разрешен с помощью autofac - PullRequest
0 голосов
/ 14 марта 2019

Вот мой код установки:

Dim builder As New ContainerBuilder
Dim assemblies = BuildManager.GetReferencedAssemblies().Cast(Of Assembly).ToArray

builder.RegisterModule(Of AutofacWebTypesModule)
builder.RegisterAssemblyTypes(assemblies).AsClosedTypesOf(GetType(IGenericRepository(Of)))

'Controllers
builder.RegisterControllers(assemblies)

'Model Binders
builder.RegisterModelBinders(assemblies)
builder.RegisterModelBinderProvider()

Dim container = builder.Build

И код контроллера:

Public Class TestController
    Inherits System.Web.Mvc.Controller

    Public Sub New(manager As IGenericRepository(Of TestObject))

    End Sub

    Public Function Test() As ContentResult

        Return Content("OK")

    End Function

End Class

Теперь, когда я перехожу к /Test/Test, я получаю следующую ошибку:

Ни один из конструкторов, найденных с 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' для типа 'MyProject.TestController', не может быть вызван с доступными службами и параметрами: Невозможно разрешить параметр 'MyProject.IGenericRepository 1[MyProject.TestObject] manager' of constructor 'Void .ctor(MyProject.IGenericRepository 1 [MyProject.TestObject]) '.

Как правильно зарегистрировать этот открытый универсальный с помощью autofac?

Я не могу использовать что-то вроде builder.RegisterGeneric(GetType(GenericRepository(Of))).As(GetType(IGenericRepository(Of))), потому что конкретный класс находится в другом, ссылка на проект

Ответы [ 2 ]

1 голос
/ 15 марта 2019

Метод AsClosedTypesOf регистрирует закрытый тип (не универсальный), который реализует определенный открытый тип.

Ваш код будет работать, если одна сборка содержит закрытую реализацию IGenericRepository<TestObject>

public class TestRespository : IGenericRepository<TestObject> 
{ }

В вашем случае вы хотите зарегистрировать открытый универсальный, без сканирования сборки это делается с помощью

builder.RegisterGeneric(typeof(GenericRepository<>)).As(typeof(IGenericRepository<>))

, но из-за ограничений, описанных в этой проблеме Github ( Поддержка регистрации открытых универсальных типов при сканировании сборок ), это невозможно.

Один из распространенных способов обхода проблемы - выполнить собственное сканирование сборки:

var repositories = assembly.GetTypes().Where(t =>
{
    return t.GetTypeInfo()
        .ImplementedInterfaces.Any(
            i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IGenericRepository<>));
});

foreach (var repository in repositories)
{
    builder.RegisterGeneric(repository).As(typeof(IGenericRepository<>));
}
0 голосов
/ 15 марта 2019

Кирилл помог мне понять, что массив assemblies содержит тип, который я хочу использовать. Таким образом, я смог обойти это:

Dim genericType = assemblies.Single(Function(x) x.FullName.Contains("OtherAssembly")).
     DefinedTypes.        
     Single(Function(x) x.FullName.Contains("GenericRepository"))
builder.RegisterGeneric(genericRepo.UnderlyingSystemType).As(GetType(IGenericRepository(Of)))
...