我想用实体框架的IDbSet<>
接口实现通用存储库模式。
当我从Autofac询问IDbSet<T>
时,它应解析IDbContext
,然后调用其Set<T>
方法返回具体类型IDbSet<T>
作为一个例子,它应该做这样的事情:
builder.Register<IDbSet<T>>(context => context.Resolve<IDbContext>().Set<T>());
我如何使用Autofac实现这一目标?
答案 0 :(得分:2)
似乎基于这个答案:https://stackoverflow.com/a/7997162/872395
唯一的解决方案是创建自定义IRegistrationSource
,您可以在其中创建已关闭的注册:
public class DbSetRegistrationSource : IRegistrationSource
{
public bool IsAdapterForIndividualComponents
{
get { return true; }
}
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service,
Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var swt = service as IServiceWithType;
if (swt == null || !swt.ServiceType.IsGenericType)
yield break;
var def = swt.ServiceType.GetGenericTypeDefinition();
if (def != typeof(IDbSet<>))
yield break;
// if you have one `IDBContext` registeration you don't need the
// foreach over the registrationAccessor(dbContextServices)
yield return RegistrationBuilder.ForDelegate((c, p) =>
{
var dBContext = c.Resolve<IDBContext>();
var m = dBContext.GetType().GetMethod("Set", new Type[] {});
var method =
m.MakeGenericMethod(swt.ServiceType.GetGenericArguments());
return method.Invoke(dBContext, null);
})
.As(service)
.CreateRegistration();
}
}
用法非常简单:
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterSource(new DbSetRegistrationSource());
containerBuilder.RegisterType<DbContext>().As<IDBContext>();
var container = containerBuilder.Build();