有没有一种方法可以缩短以下方式,而不是逐个明确地注册这些类型:
builder.RegisterType<Repo1>().Keyed<IRepository>(typeof(Repo1));
builder.RegisterType<Repo2>().Keyed<IRepository>(typeof(Repo2));
builder.RegisterType<Repo3>().Keyed<IRepository>(typeof(Repo3));
...
将每个存储库注册为IRepository接口,并将其类型作为键,以便我可以使用IIndex<Type, IRepository>
提前致谢
答案 0 :(得分:1)
您可以注册一个函数,该函数将返回给定类型的存储库,以便在您的工作单元中使用。 Func<Type, IRepository>
可以在Autofac中注册并注入您的工作单元。
// register your services as per Nico's answer
builder.Register...
// register a factory with Autofac
builder.Register<Func<Type, IRepository>>(x => {
var context = x.Resolve<IComponentContext>();
return y => {
return (IRepository) context.Resolve(y);
};
});
// use the factory in your Unit of Work
class UnitOfWork
{
readonly Func<Type, IRepository> _factory;
public void SomeMethod(object o)
{
var repository = _factory(o.GetType());
repository.DoSomething(o);
}
}
答案 1 :(得分:0)
我不确定我是否正确地遵循了这个问题,通常IRepository指向具有通用功能的数据存储库(插入,更新,删除等)。但是autofac keyed services用于使用键名(或任何键类型)注册服务。如果是这种情况,您将不得不提出一个解决方案,可以找到所有Repo
类型并在循环中单独注册它们。这可以使用Reflection实现。但是,每个对象Repo1
,Repo2
等都需要一个共同的衍生物。
例如,假设每个Repo
对象都来自接口IRepo
,那么我们可以使用反射来查找类型为IRepo
的{{1}}接口的所有实例然后遍历每个实例,将其注册到您的容器。像。的东西。
class
现在个人认为,当我通过我想要var iRepoType = typeof(IRepo);
var repoTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => type.IsClass && iRepoType.IsAssignableFrom(type))
.ToList();
foreach(var repoType in repoTypes)
{
builder.RegisterType(repoType).Keyed<IRepository>(repoType);
}
的密钥typeof(Repo1)
时,您正在说这个密钥服务时,这没有任何意义。因此,如果不使用Keyed服务注册每种类型的存储库,这不是一样的吗?
我在代码审核中发布了一个回答Repository patterns and classes的答案,这可能也有些兴趣。
答案 2 :(得分:0)
从MEF获取一些灵感,我创建了一个类似的&#34;导出属性&#34;在autofac中实现这一点。 您可以创建一个Export属性,并将其作为
的每个IRepository实现使用它[导出(typeof运算(IRepository))]
e.g. [Export(typeof(IRepository))]
class Repo1:IRepository
{}
在注册时,只需提取类型并使用RegisterGeneric(),注册您的组件。
/// <summary>
/// Export attribute to allow registering components using autofac.
/// This attribute must be used for all pluggable components that require to be discovered dynamically.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class ExportAttribute:Attribute
{
private Type type;
public ExportAttribute(Type type)
{
this.type = type;
}
/// <summary>
/// Provides the type (any interface) of Export
/// </summary>
public Type Type { get { return this.type; } }
}
/// <summary>
/// Registers components based on Export attribute containing their type information
/// </summary>
private void BuildContainer()
{
var allAssemblies = AssemblyInitializer.GetLoadedPlugins();
allAssemblies.ForEach(assembly =>
{
var allTypes = assembly.GetTypes().Where(a => a.GetCustomAttribute(typeof(ExportAttribute)) != null).ToList<Type>();
allTypes.ForEach(y =>
{
var classType = ((ExportAttribute)(y.GetCustomAttribute(typeof(ExportAttribute)))).Type;
if (!classType.IsInterface || !classType.IsAbstract || !classType.IsPublic) return;
if (classType.Equals(typeof(IRepository<>)))
{
builder.RegisterGeneric(y.GetTypeInfo()).Named(y.GetTypeInfo().Name, typeof(IRepository<>));
}
// Handle code for any other specific Interfaces
});
});
this.Container = builder.Build();
}