我想用IDbSet<>
实体框架的接口实现通用存储库模式。
当我IDbSet<T>
从 Autofac 询问时,它应该解析IDbContext
然后调用它的Set<T>
方法来返回具体类型IDbSet<T>
例如,它应该做这样的事情:
builder.Register<IDbSet<T>>(context => context.Resolve<IDbContext>().Set<T>());
我怎样才能用 Autofac 做到这一点?
我想用IDbSet<>
实体框架的接口实现通用存储库模式。
当我IDbSet<T>
从 Autofac 询问时,它应该解析IDbContext
然后调用它的Set<T>
方法来返回具体类型IDbSet<T>
例如,它应该做这样的事情:
builder.Register<IDbSet<T>>(context => context.Resolve<IDbContext>().Set<T>());
我怎样才能用 Autofac 做到这一点?
似乎基于这个答案: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();