How to use StructureMap with OpenRasta - structuremap

How do I use StructureMap with OpenRasta? Can I use it in place of the internal dependency resolver, or is it only possible to use it in conjunction with the built-in DI (i.e. for my own app's dependencies)?
Thanks

Structure map code is here
Build it then reference the library. Or you could git submodule it.
Then add the following code into your openrasta project
public class DependencyResolver : IDependencyResolverAccessor
{
public IDependencyResolver Resolver
{
get { return new StructureMapDependencyResolver(ConfigureContainer()); }
}
public static IContainer ConfigureContainer()
{
var container = new Container();
container.Configure(c => c.Scan(s =>
{
//normal SM registrations
}));
return container;
}
}
Hope it helps
p.s Structure Map isn't officially supported, you're probably better off with Castle/Ninject.

Related

StructureMap ObjectFactory.TryGetInstance cannot resolve symbol error

I am getting "Cannot Resolve Symbol Error" for StructureMap
ObjectFactory.TryGetInstance
But ObjectFactory.GetInstance is okay.
StructureMap Version 3.
Assembly include is "Using StructureMap;"
I am using this in an MVC 5 project.
Missing any other includes?'
ObjectFactory.Container.TryGetInstance is even better
ObjectFactory.Container.Try/GetInstance() is now replaced by creating a Container instance and using the methods from it. ObjectFactory was an encapsulation of Container anyway, from what I read.
public object GetService(Type serviceType)
{
// Previous way
return serviceType.IsAbstract || serviceType.IsInterface ?
ObjectFactory.Container.TryGetInstance(serviceType) :
ObjectFactory.Container.GetInstance(serviceType);
// New way
Container container = new Container();
return serviceType.IsAbstract || serviceType.IsInterface ?
container.TryGetInstance(serviceType) :
container.GetInstance(serviceType);
}
Source:
https://groups.google.com/forum/#!topic/structuremap-users/S7nBib95zh0
ObjectFactory.Container.GetInstance resolved this.
As Vahid N.'s answer may be useful in discussion :
My version, produces a lazy loaded thread safe singleton, but your Initialize method is not thread safe. Try:
public static class StructureMapObjectFactory
{
private static readonly Lazy<Container> _containerBuilder = new Lazy<Container>(() => new Container(), LazyThreadSafetyMode.ExecutionAndPublication);
public static IContainer Container
{
get { return _containerBuilder.Value; }
}
public static void Initialize<T>() where T : Registry, new()
{
Container.Configure(x =>
{
x.AddRegistry<T>();
});
}
}
And how to use :
DbContext dataContext = StructureMapObjectFactory.Container.TryGetInstance<DbContext>();

Where can I initialize AutoMapper mappings in an Orchard module?

I am busy developing my first non-example Orchard module. It is a handful of controllers and views, with custom (EF) data access, and is largely independent of Orchard content types and parts. Normally I set up mappings in an Application_Start handler, but as the actions in this MVC module will be invoked in the context of the Orchard application, I no longer have that point of entry. My most obvious and immediate solution is to move mapping initialization into static constructors for mapped view models, e.g.
public class ApplicantPersonalDetailsModel : MappedViewModel<Applicant>
{
static ApplicantPersonalDetailsModel()
{
Mapper.CreateMap<Applicant, ApplicantPersonalDetailsModel>().Bidirectional();
}
....
}
How else can I do this? is there a better way to do this in MVC3/4 in general, or preferably, an event or hook I can grab in the Orchard application to also achieve this on applicaion startup?
The way I have done it is by implementing IOrchardShellEvents
public class MenuOrchardShellEvents : IOrchardShellEvents
{
public void Activated()
{
Mapper.CreateMap<YSRB.Menu.Models.Records.Customer, YSRB.Menu.Models.ViewModels.CustomerViewModel>()
.ForMember(c => c.CustomerType,
m => m.MapFrom(
x => (CustomerTypes)x.CustomerType
)
);
Mapper.CreateMap<YSRB.Menu.Models.ViewModels.CustomerViewModel, YSRB.Menu.Models.Records.Customer>()
.ForMember(c => c.CustomerType,
m => m.MapFrom(
x => (int)x.CustomerType
)
);
}
public void Terminating()
{
//Do nothing
}
}
Hope this helps.
The Handler is the best place for initializing your variables, even if you haven't defined any part inside your module you can define one without a driver but with handler.
public class InitPartHandler : ContentHandler
{
public InitPartHandler(IRepository<InitPartRecord> repository)
{
OnInitializing<InitPart>((context, part) =>
// do your initialization here
);
}
}
EDIT
InitPart and InitPartRecord would be
public class InitPart : ContentPart<InitPartRecord>
{
}
public class InitPartRecord : ContentPartRecord
{
}

How to inject AutoMapper IMappingEngine with StructureMap

Most of the examples I've found for Automapper use the static Mapper object for managing type mappings. For my project, I need to inject an IMapperEngine as part of object construction using StructureMap so that we can mock the mapper in unit tests so we can't use the static mapper. I also need to support configuring AutoMapper Profiles.
My question is how can I configure the StructureMap registry so that it can supply an instance of IMappingEngine when an instance of MyService is constructed.
Here is the Service constructor signature:
public MyService(IMappingEngine mapper, IMyRepository myRepository, ILogger logger)
And here is the StructureMap Registry
public class MyRegistry : StructureMap.Configuration.DSL.Registry
{
public MyRegistry()
{
For<IMyRepository>().Use<MyRepository>();
For<ILogger>().Use<Logger>();
//what to do for IMappingEngine?
}
}
And the profile I want to load
public class MyAutoMapperProfile : AutoMapper.Profile
{
protected override void Configure()
{
this.CreateMap<MyModel, MyDTO>();
}
}
The Mapper class has a static property Mapper.Engine. Use this to register the engine with the container:
For<IMappingEngine>().Use(() => Mapper.Engine);
If you need to load your profiles before injecting the engine I would insert that configuration code alongside the above snippet.
Update
Your custom registry would look like this
class MyRegistry : Registry
{
public MyRegistry()
{
For<IMyRepository>().Use<MyRepository>();
For<ILogger>().Use<Logger>();
Mapper.AddProfile(new AutoMapperProfile());
For<IMappingEngine>().Use(() => Mapper.Engine);
}
}
This code runs once in your bootstrapper and any dependency of type IMappingEngine will afterwards be served with the value of the static property Mapper.Engine which is configured using your custom AutoMapperProfile.
The static API will be removed in version 5.0. Use a
MapperConfiguration instance and store statically as needed. Use
CreateMapper to create a mapper instance.
in new version (4.2.0 >=) we should hold and pass IMapper through DI.
a simple Configure Service should be like this (ASP.NET Core)
services.AddSingleton<IMapper>(_ => new MapperConfiguration(cfg =>
{
cfg.CreateMap<Foo,Bar>();
})
.CreateMapper());
and our service layer (with the help of constructor injection) :
public class CrudService<TDocument> : ICrudService<TDocument>
{
private readonly IMapper _internalMapper;
private readonly IRepository<TDocument> _repository;
public CrudService(IRepository<TDocument> repository, IMapper mapper)
{
_internalMapper = mapper;
_repository = repository;
}
public virtual ServiceResult<string> Create<TModel>(TModel foo)
{
var bar = _internalMapper.Map<TDocument>(foo);
try
{
_repository.Create(bar);
}
catch (Exception ex)
{
return ServiceResult<string>.Exception(ex);
}
return ServiceResult<string>.Okay(entity.Id);
}
}
consider TDocument as Bar, and TModel as Foo
update :
AutoMapper 4.2.1 released – Static is back
After a bit of feedback and soul searching and honestly tired of
dealing with questions, some of the static API is restored in this
release. You can now (and in the future) use Mapper.Initialize and
Mapper.Map
I wrote a blog post that shows my AutoMapper with StructureMap setup. I have created specific registries for AutoMapper 3.1.0 (also works for 3.1.1) and 3.0.0 and 2.2.1.
http://www.martijnburgers.net/post/2013/12/20/My-AutoMapper-setup-for-StructureMap.aspx
Here's what I ended up with as I couldn't figure out how to set the configuration on Mapper.Engine and have it passed into For().Use.
public MyRegistry()
{
For<IMyRepository>().Use<MyRepository>();
For<ILogger>().Use<Logger>();
//type mapping
For<ConfigurationStore>()
.Singleton()
.Use(ctx =>
{
ITypeMapFactory factory = ctx.GetInstance<ITypeMapFactory>();
ConfigurationStore store
= new ConfigurationStore(factory, MapperRegistry.AllMappers());
IConfiguration cfg = store;
cfg.AddProfile<MyAutoMapperProfile>();
store.AssertConfigurationIsValid();
return store;
});
For<IConfigurationProvider>().Use(ctx => ctx.GetInstance<ConfigurationStore>());
For<IConfiguration>().Use(ctx => ctx.GetInstance<ConfigurationStore>());
For<IMappingEngine>().Singleton().Use<MappingEngine>();
For<ITypeMapFactory>().Use<TypeMapFactory>();
}

Plugin defined with Hybrid lifecycle being instantiated more than once per HttpContext

I have a standard StructureMap-based ControllerFactory setup, and I have Controllers that have various dependencies that each have a dependency of type IRepository, like so:
// "web" assembly
public StructureMapRegistry : Registry
{
public StructureMapRegistry()
{
Scan(scanner =>
{
scanner.AssemblyContainingType<WidgetController>();
scanner.AssemblyContainingType<Repository>();
scanner.WithDefaultConventions();
});
For<IRepository>().HybridHttpOrThreadLocalScoped().Use<Repository>();
}
}
public WidgetController(IService1 service1, IService2 service2, Service3 service3)
{
// etc, etc
}
// "data" assembly
public Service1 : IService1
{
public Service1(IRepository repository)
{
// etc, etc
}
}
public Service2 : IService2
{
public Service2(IRepository repository)
{
// etc, etc
}
}
public Service3
{
public Service3(IRepository repository)
{
// etc, etc
}
}
Using debugging and GetHashCode() and the like, it seems that there's a new Repository being instantiated in each of the services when the WidgetController, when I am expecting them to all use the the same instance.
Am I misunderstanding what HybridHttpOrThreadLocalScoped() does? Is it because I'm sometimes passing in concrete classes instead of interfaces as dependences, like I did with Service3 in the code above (IRepository is ALWAYS used, never the Repository concrete class)? Am I just completely doing this wrong?
(This code was obviously extrapolated from the actual code, so I hope I didn't leave out any important details.)
NOTE: I am using StructureMap 2.6.1.
The code you have posted is correct, you should be getting the same instance of IRepository throughout your request. There must be something else going on that you have not included in your question...

Structure Map - I dont want to use the greediest constructor!

I am trying to configure the NCommon NHRepository in my project with Structure Map. How do I stop it from choosing the greediest constructor?
public class NHRepository<TEntity> : RepositoryBase<TEntity>
{
public NHRepository () {}
public NHRepository(ISession session)
{
_privateSession = session;
}
...
}
My structure map configuration
ForRequestedType(typeof (IRepository<>))
.TheDefaultIsConcreteType(typeof(NHRepository<>))
Cheers
Jake
You can set the [DefaultConstructor] Attribute for the constructor you wish as a default. In your case, setting it on the NHRepository() constructor would make it the default constuctor for StructureMap to initialize.
Update: well, in the latest version of StructureMap, using .NET 3.5 you can also specify it using the SelectConstructor method:
var container = new Container(x =>
{
x.SelectConstructor<NHRepository>(()=>new NHRepository());
});
Finally, I'm sure you would be able to define it in the XML configuration of StructureMap, but I haven't used that. You could do a little search on it. For more information on the above method, see: http://structuremap.sourceforge.net/ConstructorAndSetterInjection.htm#section3
So +1 for Razzie because this would work if the NHRepository was in my own assembly, instead I choose to wrap the NHRepository with my own Repository like below..
public class Repository<T> : NHRepository<T>
{
[DefaultConstructor]
public Repository()
{
}
public Repository(ISession session)
{
}
}
ForRequestedType(typeof (IRepository<>))
.TheDefaultIsConcreteType(typeof (Repository<>));

Resources