All examples of StructureMap that I've seen use the static ObjectFactory class to initialize and resolve objects. I however would like to pass around a reference to my container. I assume that ObjectFactory is just a singleton wrapper for a non-static object. But where is it?
Related
I see defaut template use ServiceProvder.GetService<ApplicationDbCotnext>() to initialize a DbContext,
But when you inside a Static Method, I have no idea how to get a DbContext, because there is no ServiceProvider.
Is there a way to get the ServiceProvider ?
Well, first of all, this has nothing to do with asp.net-core per se. This has more to do with how Dependency Injection works. You have to ask yourself why your method is static. Is that really necessary?
If you can't get rid of your static method, you might as well go all the way and introduce another anti-pattern, the Service Locator Pattern. In short: In the Startup class you put a reference to the ServiceProvider in a static property (call it for instance "ServiceProviderSingleton") of a static class (for instance "ServiceProviderProvider"). This way you can just call "ServiceProviderProvider.ServiceProviderSingleton.GetService()".
Again, i suggest giving your overal design a critical look. But if this is what you need/want then I hope it helped.
If we have a look at Microsoft's static methods (extension) - they seem not to use logging there - just throw appropriate Exception, for example in UseMvc method (for StartUp class):
https://github.com/aspnet/Mvc/blob/760c8f38678118734399c58c2dac981ea6e47046/src/Microsoft.AspNetCore.Mvc.Core/Builder/MvcApplicationBuilderExtensions.cs
If I have a class HelperClass that I'd like to use within a saga, I'd like to be able to inject an IHelperClass into the constructor.
The problem I'm running into is that sagas appear to be instantiated with an empty constructor; so while I can create a constructor that takes IHelperClass and use it in unit tests, the framework will always call the parameterless constructor.
I think I could use property injection, but since this helper class is "necessary," my understanding is that property injection (assuming it would work) is not a best practice.
So how can I do this without taking a hard dependency on the concrete HelperClass implementation?
You don't have to worry about the "necessity" of the help object in the context of the saga since no other code will be instantiating the saga directly.
In short, you can use property injection without concern here.
What bothers me about IoC and autowiring is the usability of IoC for objects that are created.
Lets say I have the a static Utils class, that is used across the system. When I decided to use IoC and DI, I easily changed Utils to be non-static and have all my components receive its instance.
However, auto-wiring works well only for components that are created during bootstrap, for objects that are created during run-time or as response of user operations, and that use Utils, auto-wiring doesn't work. Instead, I have to manually pass instance of Utils to every instance of every object that is created during runtime.
The only way around it that I can see is using the anti-pattern of passing the IoC container around, which I certainly wouldn't want to do.
Is there another way? Or am I forced to pass Utils manually around to every instance and class?
Note: This isn't a question of design. Sure, I could minimize the usage of this metaphorical Utils in various ways, but in many situations it is unavoidable.
The only way around it that I can see is using the anti-pattern of
passing the IoC container around, which I certainly wouldn't want to
do.
The answer is simply: use an abstract factory.
By defining the factory interface in the application and the factory implementation in the Composition Root (your bootstrapper code) you can prevent using the Service Locator anti-pattern. This factory implementation can hold a reference to the container and call it to request instances. Because that implementation is part of your bootstrapping logic, that implementation is a infrastructure component, and you are not using it as a service locator.
Example:
public interface IUnitOfWorkFactory
{
IUnitOfWork CreateNew();
}
Implementation in composition root:
internal class SimpleInjectorUnitOfWorkFactory
: IUnitOfWorkFactory
{
private readonly SimpleInjector.Container container;
public SimpleInjectorUnitOfWorkFactory(Container container)
{
this.container = container;
}
public IUnitOfWork CreateNew()
{
return this.container.GetInstance<IUnitOfWork>();
}
}
When using unity, if i attempt to inject a concrete type that i havent explicitly registered with the container, unity will attempt to locate the current type and will instantiate a new one for me, before injecting it into the class that depends upon it.
How can i ensure that only a single instance of this type is used? Do i need to explicitly register an instance with the container beforehand?
From MSDN:
You can use the Unity container to generate instances of any object that has a public constructor (in other words, objects that you can create using the new operator), without registering a mapping for that type with the container. When you call the Resolve method and specify the default instance of a type that is not registered, the container simply calls the constructor for that type and returns the result.
So simply put, yes, you have to register a mapping for your type to be able to use it as singleton in your app. You can achieve it using RegisterInstance method or RegisterType and providing the ContainerControlledLifetimeManager as the lifetime manager.
Say I have a source and destination class that is mapped using AutoMapper.
The destination has a logger service injected into the constructor.
However, I don't know how to get the service injected into the constructor through StructureMap?
I've tried the following:
Mapper.Initialize(m =>
{
m.ConstructServicesUsing(ObjectFactory.GetInstance);
});
which didn't prevent me having the exception on the mapping call, I guess because the service isn't being injected in properly.
I also tried the following:
CreateMap<Source, Dest>()
.ConstructUsing(x=> ObjectFactory.GetInstance<ILoggerService>());
But I get the error: cannot convert Lamda expression to delegate type, yet all the examples I have seen use this method?
The lambda you pass into ConstructUsing must return an instance of the destination type. So in your case, you would want to do this:
CreateMap<Source, Dest>()
.ConstructUsing(x=> ObjectFactory.GetInstance<Dest>());
Assuming you have StructureMap setup correctly, it should create the Dest object and inject the ILoggerService for you.
You can also do this:
Mapper.Configuration.ConstructServicesUsing(container.Resolve);
Mapper.CreateMap<Source, Dest>().ConstructUsingServiceLocator();