具有通用服务和存储库的 Autofac
Autofac with generic services and repository
我在尝试使用 Autofac 时遇到了架构设置的问题。
遇到的错误信息如下:
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.IGenericService2[xx.Common.Models.EntCountry,System.Int32]
countryService' of constructor 'Void
.ctor(xx.Service.Common.IGenericService
2[xx.Common.Models.EntCountry,System.Int32])'.
存储库接口和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 {}
服务接口和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{...}
控制器代码
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();
}
}
我的服务和存储库的 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();
我尝试使用 Register Generic 方法,但仍然出现相同的错误
builder.RegisterGeneric(typeof(GenericRepository<,>))
.As(typeof(IGenericRepository<,>))
.AsSelf()
.InstancePerDependency();
感谢您的帮助。
此致。
错误信息表明IGenericService<EntCountry, Int32>
没有注册。
因为 GenericService
是抽象的,第一个解决方案是实现这样的 class
public class FooService : GenericService<Foo, Int32>
{ }
然后Autofac会将FooService
注册为IGenericService<Foo, Int32>
如果您不想实现而只使用 GenericService<T, TId>
,则必须删除 abstract
修饰符并更改您在 Autofac[ 中注册类型的方式。
不幸的是,在扫描程序集时没有简单的方法来注册开放泛型类型。在 Autofac Github 中有一个活跃的未解决问题:Support registering open generic types when scanning assemblies
最简单的解决方案是手动注册此类型
builder.RegisterGeneric(typeof(GenericService<,>))
.AsImplementedInterfaces();
如果不可能,请查看 Github 问题,您可以使用一些解决方案。
所提供的代码还会有另一个问题。 IGenericService<T, TId>
有一个 class 约束(where TId : class
),但在例外情况下 TId
是一个 Int32
,它对 .net 运行时无效。您应该删除 class 约束或更改 TId
的类型。
我在尝试使用 Autofac 时遇到了架构设置的问题。
遇到的错误信息如下:
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])'.
存储库接口和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 {}
服务接口和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{...}
控制器代码
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();
}
}
我的服务和存储库的 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();
我尝试使用 Register Generic 方法,但仍然出现相同的错误
builder.RegisterGeneric(typeof(GenericRepository<,>))
.As(typeof(IGenericRepository<,>))
.AsSelf()
.InstancePerDependency();
感谢您的帮助。
此致。
错误信息表明IGenericService<EntCountry, Int32>
没有注册。
因为 GenericService
是抽象的,第一个解决方案是实现这样的 class
public class FooService : GenericService<Foo, Int32>
{ }
然后Autofac会将FooService
注册为IGenericService<Foo, Int32>
如果您不想实现而只使用 GenericService<T, TId>
,则必须删除 abstract
修饰符并更改您在 Autofac[ 中注册类型的方式。
不幸的是,在扫描程序集时没有简单的方法来注册开放泛型类型。在 Autofac Github 中有一个活跃的未解决问题:Support registering open generic types when scanning assemblies
最简单的解决方案是手动注册此类型
builder.RegisterGeneric(typeof(GenericService<,>))
.AsImplementedInterfaces();
如果不可能,请查看 Github 问题,您可以使用一些解决方案。
所提供的代码还会有另一个问题。 IGenericService<T, TId>
有一个 class 约束(where TId : class
),但在例外情况下 TId
是一个 Int32
,它对 .net 运行时无效。您应该删除 class 约束或更改 TId
的类型。