4

我想用IDbSet<>实体框架的接口实现通用存储库模式。

当我IDbSet<T>从 Autofac 询问时,它应该解析IDbContext然后调用它的Set<T>方法来返回具体类型IDbSet<T>

例如,它应该做这样的事情:

builder.Register<IDbSet<T>>(context => context.Resolve<IDbContext>().Set<T>());

我怎样才能用 Autofac 做到这一点?

4

1 回答 1

3

似乎基于这个答案: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();
于 2013-04-26T05:45:04.637 回答