Define default constructor with StructureMap witho

2019-06-01 20:55发布

问题:

I've been using StructureMap for sometime now but I'm far from an expert. My problem is simple, I'm trying to configure SM via code (Registry) to use a particular constructor when creating an instance of a repository object.

Here are my 2 constructors (note neither is the greediest).

public BusinessUnitRepository( IDatabase database )
    : base( database ) {

}

public BusinessUnitRepository( IDatabaseFactory factory )
    : base( factory ) {

}

Note: The first constructor takes an instance of the IDatabase interface and is called by the base class's ctor(IDatabaseFactory) implementation.

What I'm trying to do is configure SM to use the second constructor and provide an instance of DatabaseFactory from the SM container. I can't use the [DefaultConstructor] attribute in the assembly where BusinessUnitRepository is defined so this option is off the table.

My Registry code

ForRequestedType<IDatabaseFactory>()
    .CacheBy( InstanceScope.PerRequest )
    .TheDefaultIsConcreteType<DatabaseFactory>();


ForRequestedType<Repository.IBusinessUnitRepository>()
    .CacheBy( InstanceScope.PerRequest )
    .TheDefault.Is.OfConcreteType<BusinessUnitRepository>().CtorDependency<IDatabaseFactory>().Is<DatabaseFactory>();

When I run the program SM throws a 302 error when trying to create an instance of BusinessUnitRepository.

StructureMap.StructureMapException: StructureMap Exception Code:  302
There is no argument of type Repository.LinqToSql.IDatabaseFactory for concrete type Repository.LinqToSql.BusinessUnitRepository

FYI:

  • If I do reference StructureMap in the Repository.LinqToSql.BusinessUnitRepository assembly and use the [DefaultConstructor] attribute on my IDatabaseFactory constructor everything works perfectly.
  • Also I have confirmed that StructureMap does contain a configured 'Repository.LinqToSql.DatabaseFactory'

回答1:

I found a solution but the 'magic' has a stink:

ForRequestedType<Repository.IBusinessUnitRepository>()
            .CacheBy( InstanceScope.PerRequest )
            .TheDefault.Is.OfConcreteType<BusinessUnitRepository>()
            .CtorDependency<IDatabaseFactory>("factory").IsTheDefault();

SelectConstructor<BusinessUnitRepository>( () => new BusinessUnitRepository((IDatabaseFactory)null ) );

I still think there is a better answer. Since I have quite a few Repository interfaces and concrete implementation it seems like a lot of work to define the SelectConstructor for each type. I'm open to suggestions.