1

Here is my incomplete StructureMap configuration:

PS: Big apologies for asking you to write my app for me but I'm finding the StructureMap api to be a bit confusing as nearly everything I find when I do google searches refers to the older api.

    public static void Configure(IContainer container)
    {
        container.Configure(c =>
        {
            string connectionString = ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString;
            SQLDataContext dataContext = new SQLDataContext(connectionString);

            c.For<SQLDataContext>().HttpContextScoped();

            c.For<IAdminRepository>().Use<SQLAdminRepository_v2>().Ctor<SQLDataContext>().Is(dataContext);
            c.For<IMemberRepository>().Use<SQLMemberRepository_v2>().Ctor<SQLDataContext>().Is(dataContext);
            c.For<IUtilityRepository>().Use<SQLUtilityRepository_v2>().Ctor<SQLDataContext>().Is(dataContext);

            c.For<IAdminService>().Use<AdminService_v2>();
            c.For<IMemberService>().Use<MemberService_v2>();
            c.For<IUtilityService>().Use<UtilityService_v2>();

            c.For<ResourcePool>().Singleton();

        });
    }

Each Service has a dependency on the corresponding Repository which is passed in via its constructor. e.g. :

public class ContactService_v2 : IContactService
{
    IContactRepository contactRepository;

    public ContactService_v2(IContactRepository contactRepository)
    {
        this.contactRepository = contactRepository;
    }

    public IQueryable<Contact> Get_Contacts()
    {
        return contactRepository.GetContacts();
    }

    public void Save_Contact(Contact contact)
    {
        contactRepository.Save_Contact(contact);
    }
}

So the Service layer is just facade with the real Repository lying behind it. [and before you ask or suggest - No I won't be changing that in a hurry because initially I just want to get the DI working to make the code testable before I start doing anything dramatic.]

Q1: The application uses Linq2Sql data access. It is essential that all the Services sent to each controller have, in their Repository dependency a dependency on the same data context instance, because they may need to join to each other in complex queries made across Repositories. Therefore I want to use a HttpContext lifecycle for the data context. Is this (above) how I do that?

Q2: The ResourcePool used to follow a singleton pattern but I have refactored it to a ordinary class taking a single service as its constructor parameter. Is that right? In this case, will it behave as if it came from the asp.net application cache?

Q3: What are the auto-registration equivalents for the Repository and Service configurations? [PS: Yes I know that the "_v2" suffix is unconventional but there already exist legacy equivalents of each XService and XRepository which I wish to refactor away at my leisure after the DI has been added and is working seamlessly].

Asp.Net MVC allows one to have strong model binding like so :

[HttpPost]
public ActionResult List(AdminDisplay admin)
{
    admin.GetAdminPage();
    return View(admin);
}

In such a case every class (such as AdminDisplay) requires a default parameterless constructor so that the MVC framework can create it. Furthermore any class created inside such a model bound class also needs such a parameterless constructor.

Q4: If I want to replace these parameterless constructors, is it sufficient to just add the entries for them in the StructurMap configuration code? - or do I not need to do that provided that all these model binding classes and their dependents have contructors which only use parameters what StructureMap is able to resolve.

Apologies for the bad formatting above but how do I turn off wysiwyg editing?

PS: It is permissible to provide answer any of the questions Q1, Q2, Q3, Q4 without answering all of them!

3
  • 2
    Welcome to Stack Overflow. You are more likely to get answers if you ask several, short questions, rather than one long question with lots of sub-questions in them. In addition, if it's permissible to answer any (but not all) of the questions, then how are you going to pick and accepted answer? Commented Mar 1, 2012 at 13:05
  • Thanks Mark, As noted in the last PS above - it is acceptable to answer any of these questions individually. Commented Mar 2, 2012 at 16:02
  • I was a bit worried about this because I thought it was broke - but it was something in my new repo layer which was broke instead! The code above works. Phew. The major difference is that I will set the lifetime for the data context before invoking the instance, like so: code c.For<SQLDataContext>().HttpContextScoped(); SQLDataContext dataContext = new SQLDataContext(connectionString); code Commented Mar 2, 2012 at 16:34

1 Answer 1

1

Q1: Change the code for the data context from:

SQLDataContext dataContext = new SQLDataContext(connectionString);
c.For<SQLDataContext>().HttpContextScoped();

to:

c.For<SQLDataContext>().HybridHttpOrThreadLocalScoped()
.Use(() => new SQLDataContext(connectionString));

Change the code for each repository from:

c.For<IAdminRepository>().Use<SQLAdminRepository_v2>()
.Ctor<SQLDataContext>().Is(dataContext);

to:

c.For<IAdminRepository>().Use<SQLAdminRepository_v2>()
.Ctor<SQLDataContext>();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.