简体   繁体   English

具有通用服务和存储库的Autofac

[英]Autofac with generic services and repository

I'am facing an issue with the architecture set in place while trying to use Autofac. 尝试使用Autofac时,我面临的体系结构设置问题。

Error message encountered is the following: 遇到的错误消息如下:

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'xx.xx.xxxxxxx.HomeController' can be invoked with the available services and parameters: Cannot resolve parameter 'xx.Service.Common.IGenericService 2[xx.Common.Models.EntCountry,System.Int32] countryService' of constructor 'Void .ctor(xx.Service.Common.IGenericService 2[xx.Common.Models.EntCountry,System.Int32])'. 在类型为“ xx.xx.xxxxxxx.HomeController”上使用“ Autofac.Core.Activators.Reflection.DefaultConstructorFinder”找到的构造函数均无法使用可用的服务和参数进行调用:无法解析参数“ xx.Service.Common.IGenericService 2[xx.Common.Models.EntCountry,System.Int32] countryService' of constructor 'Void .ctor(xx.Service.Common.IGenericService 2 [xx.Common.Models.EntCountry,System.Int32])的2[xx.Common.Models.EntCountry,System.Int32] countryService' of constructor 'Void .ctor(xx.Service.Common.IGenericService '。

Repository Interface and Class 存储库接口和类

 public interface IGenericRepository<T,TId> 
        where T: class , IEntity<TId>
    {...}

 public abstract class GenericRepository<T, TId> : IGenericRepository<T, TId>  
        where T : class, IEntity<TId>
        where TId : class {}

Service Interface and Class 服务接口和类别

 public interface IGenericService<T,TId> where T : class , IEntity<TId> 
    {...}



public abstract class GenericService<T, TId> : IGenericService<T, TId>  
        where T : class, IEntity<TId> 
        where TId : class{...}

Controller Code 控制器代码

   public class HomeController : Controller
    {

    private readonly IGenericService<EntCountry, int> _countryService;

    public HomeController(IGenericService<EntCountry, int> countryService)
    {
        _countryService = countryService;
    }

    // GET: Home
    public ActionResult Index()
    {

        var countries = _countryService.GetAll();

        return View();
    }
}

My Autofac configuration for services and repository is the following: 我对服务和存储库的Autofac配置如下:

builder.RegisterAssemblyTypes(Assembly.Load("XX.Data"))
                   .Where(t => t.Name.EndsWith("Repository"))
                   .AsImplementedInterfaces()
                   .AsSelf()
     .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                   .InstancePerLifetimeScope();





 builder.RegisterAssemblyTypes(Assembly.Load("XX.Service"))
                   .Where(t => t.Name.EndsWith("Service"))
                   .AsImplementedInterfaces()
                   .AsSelf()
                   .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
                   .InstancePerLifetimeScope();

I tried to use the Register Generic method, but I still got the same error 我尝试使用Register Generic方法,但仍然遇到相同的错误

builder.RegisterGeneric(typeof(GenericRepository<,>))
                .As(typeof(IGenericRepository<,>))
                .AsSelf()
                .InstancePerDependency();

Thanks for your help. 谢谢你的帮助。

best regards. 最好的祝福。

The error message indicates that IGenericService<EntCountry, Int32> is not registered. 错误消息指示未注册IGenericService<EntCountry, Int32>

Because GenericService is abstract the first solution would be to have an implementation of such a class 因为GenericService是抽象的,所以第一个解决方案是拥有这样一个类的实现。

public class FooService : GenericService<Foo, Int32> 
{ }

Then Autofac will register FooService as IGenericService<Foo, Int32> 然后Autofac将注册FooService作为IGenericService<Foo, Int32>

If you don't want to have an implementation but only use GenericService<T, TId> you will have to remove the abstract modifier and change how you register your type in Autofac . 如果您不想实现,而只使用GenericService<T, TId> ,则必须删除abstract修饰符,并更改在Autofac中注册类型的方式

Unfortunately there is no easy way to register an open generic type when scanning assemblies. 不幸的是,在扫描程序集时,没有简单的方法来注册开放的泛型类型。 There is an active open issue about this in Autofac Github : Support registering open generic types when scanning assemblies Autofac Github中对此有一个未解决的问题: 支持在扫描程序集时注册开放的通用类型

The easiest solution is to register this type manually 最简单的解决方案是手动注册此类型

builder.RegisterGeneric(typeof(GenericService<,>))
       .AsImplementedInterfaces();

If it is not possible have a look at the Github issue there is some solution you could play with. 如果不可能,请查看Github问题,可以使用一些解决方案。


There will also be another issue with the code provided. 所提供的代码也会有另一个问题。 The IGenericService<T, TId> has a class constraint ( where TId : class ) but in the exception TId is a Int32 wich is not valid for the .net runtime. IGenericService<T, TId>具有类约束( where TId : class ),但例外是TIdInt32 ,对于.net运行时无效。 You should remove the class constraint or change the type of TId . 您应该删除类约束或更改TId的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM