简体   繁体   中英

How to resolve multiple implementations of the same type in StructureMap DI and MVC 5

I have an interface which is implemented by 4 class. In my company controller class constructor I injecting it.

Below is my code:

public  interface ICompanyRepository
{
    IEnumerable<Company> GetAll();
    Company Get(int id);
    Company Add(Company item);
    bool Update(Company item);
    bool Delete(int id);
}

public class CompanyRepository1: ICompanyRepository
{
    //Implemented all the methods of the interface 
}

public class CompanyRepository2: ICompanyRepository
{
    //Implemented all the methods of the interface 
}

public class CompanyRepository3: ICompanyRepository
{
    //Implemented all the methods of the interface 
}

Now in my StructureMap code

==================================================

public static class IoC
{
    public static IContainer Initialize()
    {
        return new Container(c => c.AddRegistry<DefaultRegistry>());
    }
}

public class DefaultRegistry : Registry
{
    #region Constructors and Destructors
    public DefaultRegistry()
    {
        Scan(
            scan =>
            {
               scan.TheCallingAssembly();
               scan.WithDefaultConventions();
               // scan.AddAllTypesOf<ICompanyRepository>();
               scan.With(new ControllerConvention());
            });
        For<ICompanyRepository>().Add<CompanyRepository1>().Named("comRep1");
        For<ICompanyRepository>().Add<CompanyRepository2>().Named("comRep2");
        For<ICompanyRepository>().Add<CompanyRepository3>().Named("comRep3");
    }
    #endregion
}

==================================================

In Customer controller class I have defined like this:

public class CompanyController : Controller
{
    readonly ICompanyRepository _companyRepository1;
    readonly ICompanyRepository _companyRepository2;
    readonly ICompanyRepository _companyRepository3;
    public CompanyController(ICompanyRepository comRep1,ICompanyRepository comRep2, ICompanyRepository comRep3)
    {
        _companyRepository1 = comRep1;
        _companyRepository2 = comRep2;
        _companyRepository2 = comRep3;
    }
}

========================================================

Now by default it load only the data from comRep1 for all the three(comRep1,comRep2,comRep3)

Is there anything that I am missing here?

One more question: my interface is implemented by 10 classes, so should I specify all the 10 class and named instance like below?

For<ICompanyRepository>().Add<CompanyRepository1>().Named("comRep1");
For<ICompanyRepository>().Add<CompanyRepository2>().Named("comRep2");
......
For<ICompanyRepository>().Add<CompanyRepository3>().Named("comRep10");

The typical way to solve this is to make a generic repository. The generic repository saves you from having to rewrite the same CRUD code over and over for each entity.

Generic Repository

public interface IRepository<TEntity>
    where TEntity : class
{
    IEnumerable<TEntity> GetAll();
    TEntity Get(int id);
    TEntity Add(TEntity item);
    bool Update(TEntity item);
    bool Delete(int id);
}

public class Repository<TEntity> : IRepository<TEntity>
    where TEntity : class
{
    // Implement all the methods of the interface 
}

Example Usage

You can then use the generics to easily select one of the repositories in your services (despite the fact they all use the same class). There is no need to use named instances, since they are keyed based on the generic type.

class Program
{
    static void Main(string[] args)
    {
        var container = new Container(c =>
        {
            c.For<IService>().Use<Service>();
            // Register the generic repository for any entity
            c.For(typeof(IRepository<>)).Use(typeof(Repository<>));
        });

        // Resolve the service
        var service = container.GetInstance<IService>();
    }
}

public class Company { }
public class Employee { }
public class Timecard { }

public interface IService { }
public class Service : IService
{
    public Service(
        IRepository<Company> companyRepo, 
        IRepository<Employee> employeeRepo, 
        IRepository<Timecard> timecardRepo)
    {
        // All 3 repositories injected here
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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