views:

130

answers:

1

There's a few questions on SO about StructureMap and generics, and I've read a few blog posts about it, but still I'm struggling to figure out the solution to this particular scenario.

Given:

public interface ILookup
{
}

public interface ISupplier : ILookup
{
}

public interface ITenant : ILookup
{
}

public class Supplier : ISupplier
{
}

public class Tenant : ITenant
{
}

public interface ILookupRepository<TLookup> where TLookup : ILookup
{
   void DoSomethingWith(TLookup lookup);
}

public class LookupRepository<TLookup> : ILookupRepository<TLookup> where TLookup : ILookup
{
   public void DoSomethingWith(TLookup lookup)
   {
      SaveOrWhatever(lookup);
   }
}

public class SomeClass
{   
   public void ProcessLookup(ILookup lookup)
   {
      // Get hold of a concrete class for ILookupRepository<TLookup> where TLookup is the type of the supplied
      // lookup. For example, if ProcessLookup is passed an ISupplier I want a LookupRepository<ISupplier>.
      // If it's passed an ITenant I want a LookupRepository<ITenant>.

      // var repository = ???

      repository.DoSomethingWith(lookup);
   }
}

How do I get StructureMap to supply SomeClass.ProcessLookup with the corresponding LookupRepository<ISupplier> or LookupRepository<ITenant>? Is this possible without reflection? Can I alternatively get a LookupRepository<Supplier> or LookupRepository<Tenant> instead?

Update:

Having read Richard's initial response I've realised that my original question didn't express my problem very well (it is Friday after all!). I'm dealing with more than just one implementation of ILookup and want to be able to get the right ILookupRepository for the type I'm supplied. I've updated the question above to hopefully reflect my requirements more accurately.

Update 2:

The immediate need to crack this has passed as we've taken a slightly different approach. However I'm still interested in hearing additional suggestions to Richard's.

+1  A: 

[Edited as initial responses did not answer the real question]

When I have needed to do something similar, I use named instances. Unfortunately, I can't think of any easy way to do what you need without introducing a non-generic interface too. The non-generic interface would look like this (and would hopefully not actually be public):

public interface ILookupRepository
{
   void DoSomethingWith(object lookup);
}

Make ILookupRepository inherit from the non-generic ILookupRegistry interface. Then in StructureMap 2.5.4 you could do something like this:

 For<ILookupRepository>().Add<LookupRepository<Supplier>>()  
    .Named(typeof(Supplier).FullName);
 For<ILookupRepository>().Add<LookupRepository<Tenant>>()  
    .Named(typeof(Tenant).FullName);

Then obtain the lookup repository in your method using

var repo = ObjectFactory.GetInstance<ILookupRepository>(lookup.GetType().FullName);

NOTE: It might be better (if possible) if the ILookup interface provides the mechanism to determine the type. E.g. the concrete Tenant (or anything that inherits from it) would return "ITenant", allowing the same lookup repository to be reused when applicable.

Does it help now?

Richard J Foster
Thanks for your response. I think I should have been clearer than I was in my question as this doesn't help unfortunately. I'll update my question with more information.
Luke Bennett
I've updated my answer too... I'm not exactly happy with it (there is probably a better solution), but it may point you in the right direction.
Richard J Foster
This does give some food for thought, thanks.
Luke Bennett