从AutoFac </t>解析IDbSet <t>

时间:2013-04-25 21:17:31

标签: entity-framework autofac

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

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

作为一个例子,它应该做这样的事情:

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

我如何使用Autofac实现这一目标?

1 个答案:

答案 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();