简体   繁体   English

解析IDbSet <T> 来自AutoFac

[英]Resolving IDbSet<T> from AutoFac

I would like to implement generic repository pattern with IDbSet<> interface of Entity Framework. 我想用Entity Framework的IDbSet<>接口实现通用存储库模式。

When i ask IDbSet<T> from Autofac, It should resolve IDbContext then call its Set<T> method to return the concrete type of IDbSet<T> 当我从Autofac询问IDbSet<T>时,它应解析IDbContext然后调用其Set<T>方法返回IDbSet<T>的具体类型IDbSet<T>

As an example, it should be doing something like this: 作为一个例子,它应该做这样的事情:

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

How can i achive this with Autofac? 我如何使用Autofac实现这一目标?

It seems based on this answer: https://stackoverflow.com/a/7997162/872395 它似乎基于这个答案: https//stackoverflow.com/a/7997162/872395

that the only solution is to create a custom IRegistrationSource where you create the closed registrations: 唯一的解决方案是创建一个自定义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();
    }
}

The usage is very simple: 用法很简单:

var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterSource(new DbSetRegistrationSource());
containerBuilder.RegisterType<DbContext>().As<IDBContext>();
var container = containerBuilder.Build();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM