Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StructureMap - How to register and resolve an open generic type

public interface IRepository<T> where T : Entity
{
    void Delete(T entity);
    T[] GetAll();
    T GetById(int id);
    void SaveOrUpdate(T enity);
    void Merge(T entity);
}

public interface ITeamEmployeeRepository : IRepository<TeamEmployee>
{
    PagedList<TeamEmployee> GetPagedTeamEmployees(int pageIndex, int pageSize);
}


public class Repository<T> : IRepository<T> where T : Entity
{
    private readonly ISession _session;

    protected Repository()
    {
        _session = GetSession();
    }

    public virtual void Delete(T entity)
    {
        _session.Delete(entity);
    }

    public virtual T[] GetAll()
    {
        return _session.CreateCriteria<T>().List<T>().ToArray();
    }

    public virtual T GetById(int id)
    {
        return _session.Get<T>(id);
    }

    public virtual void SaveOrUpdate(T enity)
    {
        _session.SaveOrUpdate(enity);
    }

    public void Merge(T entity)
    {
        _session.Merge(entity);
    }

    protected ISession GetSession()
    {
        return new SessionBuilder().GetSession();
    }
}

public class TeamEmployeeRepository : Repository<TeamEmployee>, ITeamEmployeeRepository
{
    public PagedList<TeamEmployee> GetPagedTeamEmployees(int pageIndex, int pageSize)
    {
        return GetSession().QueryOver<TeamEmployee>()
            .Fetch(x => x.Employee).Eager
            .Fetch(x => x.Team).Eager
            .ToPagedList(pageIndex, pageSize);
    }
}

For now I register the repository as follows:

For<ILoanedItemRepository>().Use<LoanedItemRepository>();
For<ITeamEmployeeRepository>().Use<TeamEmployeeRepository>();
For<IArticleRepository>().Use<ArticleRepository>();
For<ISalesmanRepository>().Use<SalesmanRepository>();
For<ISalesmanArticleRepository>().Use<SalesmanArticleRepository>();
For<IGoodsGroupRepository>().Use<GoodsGroupRepository>();
For<IEmployeeRepository>().Use<EmployeeRepository>();

This is really cumbersome, especially if there comes along new repositories.

An easier and better registration would be:

For(typeof(IRepository<>)).Use(typeof(Repository<>));

But this does not work. StructureMap is everytime saying me that no Default Instance defined for PluginFamily Core.Domain.Bases.Repositories.ITeamEmployeeRepository.

I searched on stackoverflow and found something new:

Scan(x =>
{
    x.AssemblyContainingType(typeof(TeamEmployeeRepository));
    x.AddAllTypesOf(typeof (IRepository<>));
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
});

But still the same error message.

How do I have to register my repositories with StructureMap 2.6.1.0?

like image 534
Rookian Avatar asked Oct 31 '10 12:10

Rookian


2 Answers

I' ve found a solution.

Scan(x =>
{
    x.WithDefaultConventions();
    x.AssemblyContainingType(typeof(TeamEmployeeRepository));
    x.AddAllTypesOf(typeof(Repository<>));
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>));
});

WithDefaultConventions is the important part of the shown code, because with this setting you say StructureMap to use the convention of mappping ITeamEmployeeRepository to TeamEmployeeRepository. So StructureMap proceed from the assumption that the class is named like the name of the interface without the prefix I.

like image 58
Rookian Avatar answered Oct 19 '22 01:10

Rookian


I found this question googling "structuremap resolve generic". The existing answers are good but complex. For those seeking simple answer: for interface ISome and implementing class Some we write

c.For<ISome>().Use<Some>()

While for generic ISome<T> and implementing class Some<T> we write

c.For(typeof(ISome<>)).Use(typeof(Some<>))

And that's all

like image 33
Rustam Avatar answered Oct 19 '22 02:10

Rustam