views:

44

answers:

2

I have a constructor that take two interfaces, they are the same interface, but need to be different implementations:

public class Foo
{
    public Foo(IBar publicData, IBar privateData)
    {
    }
}

What I'd like to happen is that structuremap would pass in a concrete implementation of IBar as class PublicData and class PrivateData for the different arguments. Is this possible?

UPDATE

In fact, to make sure there is enough information:

The real classes that I'm working with look like this:

public abstract class EFRepository<T> : IRepository<T>
{
    protected EFRepository(IUnitOfWork publicUnitOfWork, 
                           IUnitOfWork privateUnitOfWork)
    {

    }
}

And an implementation of EFRepository might look like this:

public partial class ClaimRepository: EFRepository<Claim>, IClaimRepository
{
    public ClaimRepository(IUnitOfWork publishedUnitOfWork, 
                          IUnitOfWork unpublisedUnitOfWork) 
           : base(publishedUnitOfWork, unpublisedUnitOfWork)
    {
    }
}

So when I request and instance of IClaimRepository from structure map I want the implementation to be given the correct unit of work objects, which in my instance are essentially two different databases, so it's the same code with different connection strings.

+1  A: 

Haven't compiled and tested, but it should work in principle:

For<IBar>.Add<PublicData>.Named("public");
For<IBar>.Add<PrivateData>.Named("private");

For<IFoo>.Use<Foo>()
  .Ctor<IBar>("publicData").Is(d => d.TheInstanceNamed("public"))
  .Ctor<IBar>("privateData").Is(d => d.TheInstanceNamed("private"));

Edit: For making this by convention an IRegistrationConvention could be used

public class FooConvention : IRegistrationConvention
{
  static readonly Type PluginType = typeof(IFoo);

  public void Process(Type type, Registry registry)
  {
     if (type.IsAbstract || !type.IsClass || !PluginType.IsAssignableFrom(type))
       return;

      registry.For(PluginType).Add(type)
         .CtorDependency<IBar>("publicData")
         .IsNamedInstance("public")
         .CtorDependency<IBar>("privateData")
         .IsNamedInstance("private");
  }
}

The convention would be applied in a scan

Scan(scan => 
{
  scan.AssemblyContainingType<IFoo>();
  scan.Convention<FooConvention>();
}

See the Scanning Assemblies section in the SM docs for further info.

PHeiberg
Is there a way that this can be applied to a conventions based system? I'd rather not have to manually wire up all my repositories.
ilivewithian
See my edit for a possible approach that I have used.
PHeiberg
A: 

Setup the configuration as follows:

For<IFoo>.Use<Foo>();
For<IBar>.Use<IBar>();

Then get the instances as follows:

IBar privateData = ObjectFactory.GetInstance<IBar>();
IBar publicData = ObjectFactory.GetInstance<IBar>();

IFoo foo = ObjectFactory
    .With<IBar>(publicData)
    .With<IBar>(privateBar)
    .GetInstance<IFoo>();

This is just a suggestion. I stand corrected :-)

Waliaula Makokha