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

2019-08-17 06:08发布

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>

2条回答
手持菜刀,她持情操
2楼-- · 2019-08-17 06:43

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>>();
    }
}
查看更多
▲ chillily
3楼-- · 2019-08-17 06:49

Try this:

builder.RegisterGeneric(typeof(RepositoryBase<,>))
         .As(typeof(IDataAccess<>))
         .InstancePerRequest();
查看更多
登录 后发表回答