Autofac - How to register a class<,> to interface<>

这一生的挚爱 提交于 2019-12-24 21:28:46

问题


I'm trying to register my repository class which is take two generic parameter to repository interface (one parameter generic).

public class RepositoryBase<T, O> : IDataAccess<T>

public interface IDataAccess<T>

回答1:


Autofac don't know how to set the second generic parameter of RepositoryBase when you only want to provide one generic argument in the interface. So you need to somehow specify the second argument in order to instantiate the service unless you are happy with object, dynamic or some base class. In order to achieve this you can create a factory like this:

public class BaseRepositoryFactory<T1> : IDataAccessFactory<T1>
{
    private readonly IComponentContext context;

    public BaseRepositoryFactory(IComponentContext context)
    {
        this.context = context;
    }

    public IDataAccess<T1> Create<T2>()
    {
        return context.Resolve<IRepositoryBase<T1, T2>>();
    }
}

public interface IDataAccessFactory<T1>
{
    IDataAccess<T1> Create<T>();
}

public interface IRepositoryBase<T1, T2> : IDataAccess<T1>
{
}

public class RepositoryBase<T1, T2> : IDataAccess<T1>, IRepositoryBase<T1, T2>
{
}

And then register the services like:

builder.RegisterGeneric(typeof(BaseRepositoryFactory<>))
    .As(typeof(IDataAccessFactory<>));
builder.RegisterGeneric(typeof(RepositoryBase<,>))
    .As(typeof(IRepositoryBase<,>));

After that you can resolve the factory and create service;

var factory = c.Resolve<IDataAccessFactory<string>>();
IDataAccess<string> serviceInterface = factory.Create<int>(); 
var serviceConcrete = (RepositoryBase<string, int>)factory.Create<int>();

So this way you can move the declaration of a second argument to a factory method. The drawback of this is that you need to create such factories for each type. To avoid this you can define additional interface with two generic arugments IDataAccess<T1, T2> and implement it in concrete class and register it so your factory can look like this and will work for any type:

public class DataAccessFactory<T1> : IDataAccessFactory<T1>
{
    private readonly IComponentContext context;

    public DataAccessFactory(IComponentContext context)
    {
        this.context = context;
    }

    public IDataAccess<T1> Create<T2>()
    {
        return context.Resolve<IDataAccess<T1, T2>>();
    }
}



回答2:


Try this:

builder.RegisterGeneric(typeof(RepositoryBase<,>))
         .As(typeof(IDataAccess<>))
         .InstancePerRequest();


来源:https://stackoverflow.com/questions/49508546/autofac-how-to-register-a-class-to-interface

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!