Configuring structuremap to create an instance using a factory class - structuremap

I want to configure structuremap to create a service using a factory class. The factory itself has a dependency that needs filling. Currently I have the following in my Registry class:
For<IDoStuffWebService>().Singleton().Use(() =>
new DoStuffWebServiceClientFactory(new ConfigProvider()).Create()
);
Rather than having to hard-code the concrete type DoStuffWebServiceClientFactory and manually fill it's dependency, I want structuremap to get this for me (it implements IDoStuffWebServiceClientFactory). It looks like IContext might help (http://docs.structuremap.net/UsingSessionContext.htm), but I'm struggling to figure out how this fits.
Any help greatly appreciated.
Roger.

To use the structuremap context in a Use method you can use the overload method that have a context as a parameter.
For<IDoStuffWebService>().Singleton().Use(ctx => ctx.GetInstance<IDoStuffWebServiceClientFactory>().Create());

Related

What advantages of factory constructor over standalone factory class or function?

I've just started learning Dart and I wonder what advantages of factory constructor over standalone factory class or function?
When we add new derived class then we need to change factory method inside of our abstract class, it is fine if we have its code, but if it comes with library - factory constructor becomes useless?
Or there is some mechanism to update factory method with info about derived classes? If it so, please share an example.
factory lets you return subtypes, which is very useful.
For instance, you could have factory MyClass.empty => const _EmpytMyClass() and return a trivial implementation with no storage.
You can also use it to returned cached values if you want to have canonical instances of your class.
You can also use factory to call methods to create your instances. See here: https://github.com/dart-lang/json_serializable/blob/4033f6ad4e3c96bc2ed16d93c0995e11fcfe42df/example/lib/example.dart#L29

add new object in IOC container without having to specify every consturctor param

I'm trying to add a class to my scoped service in .net core 2.1, I don't want a provider to get all the services needed to satisfy the params of the constructor. Is there an easier way to do this?
services.AddScoped<BarcodePage>((provider) =>
new BarcodePage(provider.GetService<IObservationRepository>(),
provider.GetService<IPageFactory>(),
provider.GetService<IMediator>(),
provider.GetService<IUserRepository>()));
You could just register it as
services.AddScoped<BarcodePage>();
The container will resolve the BarcodePage class dependencies for you.

Telling StructureMap to use another Constructor

I have a class with 2 constructors.
MyClass()
and
MyClass(IMyService service)
How do I tell StructureMap then whenever I do a 'new MyClass()' it should actually call the second constructor and not the first constructor.
Please help.
If you call new MyClass(), then StructureMap is not involved at all. No amount of StructureMap configuration will change the behavior.
If you call ObjectFactory.GetInstance<MyClass>(), StructureMap will by default call the constructor with more parameters.
If you want StructureMap to use a different constructor, you can specify the constructor (via PHeiberg's answer):
x.SelectConstructor<IMyClass>(() => new MyClass(null));
Or you can just tell StructureMap explicitly how to create the instance using the overload of Use() that accepts a Func<>:
x.For<IMyClass>().Use(ctx => new MyClass(ctx.GetInstance<IMyService>()))
Joshua's answer is covering all aspects. As a side note in order to configure Structuremap to choose a specific constructor without hardcoding the arguments to the constructor as done in Joshua's example you can use the SelectContructor method:
x.SelectConstructor<MyService>(() => new MyService());
The lambda in the SelectConstructor method call should invoke the needed constructor (put nulls or any value of the correct type for all parameters present). See the documentation for further info.
When using a DI container like structuremap it's best to have just a single constructor on every class. This constructor has to resolve all the dependencies of the class, if IMyService is a dependency (which looks a bit strange though) this should always be resolved when instantiating so the parameterless constructor is not needed.

Inject service into an AutoMapper destination class

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();

How to avoid having injector.createInstance() all over the place when using guice?

There's something I just don't get about guice: According to what I've read so far, I'm supposed to use the Injector only in my bootstrapping class (in a standalone application this would typically be in the main() method), like in the example below (taken from the guice documentation):
public static void main(String[] args) {
/*
* Guice.createInjector() takes your Modules, and returns a new Injector
* instance. Most applications will call this method exactly once, in their
* main() method.
*/
Injector injector = Guice.createInjector(new BillingModule());
/*
* Now that we've got the injector, we can build objects.
*/
RealBillingService billingService = injector.getInstance(RealBillingService.class);
...
}
But what if not all Objects I ever need can be created during startup? Maybe I want to respond to some user interaction when the application is running? Don't I have to keep my injector around somewhere (e.g. as a static variable) and then call injector.getInstance(SomeInterface.class) when I need to create a new object?
Of course spreading calls to Injector.getInstance() all over the place seems not to be desirable.
What am I getting wrong here?
Yes, you basically only should use the Injector to create get the instance for the root-object. The rest of the application shouldn't touch the Guice-Container. As you've noticed, you still need to create some objects when required. There are different approaches for doing that, each suitable for different needs.
Inject a Provider
Provider is a interface from Guice. It allows you to request a new instance of a object. That object will be created using Guice. For example.
class MyService{
private Provider<Transaction> transactionProvider;
public MainGui(Provider<Transaction> transactionProvider){
this.transactionProvider = transactionProvider;
}
public void actionStarted(){
Transaction transaction = transactionProvider.get();
}
Build a Factory
Often you need some kind of factory. This factory uses some injected services and some parameters and creates a new object for you. Then you use this factory for new instances. Then you inject that factory and use it. There also help for this with the AssistedInject-extension
I think with these two possibilities you rarely need to use the Guice-Injector itself. However sometimes is still appropriate to use the injector itself. Then you can inject the Injector to a component.
To extend on the answer Gamlor posted, you need to also differentiate between the object types you are using.
For services, injection is the correct solution, however, don't try to always make data objects (which are generally the leafs in your object graph) injectable. There may be situations where that is the correct solution, but injecting a Provider<List> is probably not a good idea. A colleague of mine ended up do that, it made the code base very confusing after a while. We just finished cleaning it all out and the Guice modules are much more specific now.
In the abstract, I think the general idea is that if responding to user events is part of the capabilities of your application, then, well...
BillingService billingService = injector.getInstance(BillingService.class);
billingService.respondToUserEvent( event );
I guess that might be a little abstract, but the basic idea is that you get from Guice your top-level application class. Judging from your question, I guess that maybe BillingService isn't your top-level class?

Resources