Override service mapping settings in structureMap - structuremap

Can I override service mapping for StructureMap settings of added registry:
return new Container(x => {
For<IService>().Use<OverridenService>
x.AddRegistry<MyRegistry>();
For<IService>().Use<OverridenService>
}
public class MyRegistry: Registry
{
public MyRegistry()
{
For<IService>().Use<MyService>
}
}
I want OverridenService to be instantiated, but StructureMap instantiates MyService always

So, let's say you have this code (this code assigns the container to a variable that you can later return):
var container = new Container(x =>
{
x.AddRegistry<MyRegistry>();
});
You can simply use the Configure method like this:
container.Configure(x => x.For<IService>().Use<OverridenService>());

Related

Using MassTransit with StructureMap Registry classes

I'm using MassTransit (5.5.5) with StructureMap (4.7) in a large code base, using Registry classes to keep my dependencies organized, following what's outlined here:
class BusRegistry : Registry
{
public BusRegistry()
{
For<IBusControl>(new SingletonLifecycle())
.Use(context => Bus.Factory.CreateUsingInMemory(x =>
{
x.ReceiveEndpoint("customer_update_queue", e => e.LoadFrom(context));
}));
Forward<IBusControl, IBus>();
}
}
// Snip...
public void CreateContainer()
{
_container = new Container(x => {
x.AddRegistry(new BusRegistry());
});
}
However, the LoadFrom extension method used in the call to ReceiveEndpoint is deprecated. So how is one supposed to use MassTransit with StructureMap Registry classes currently?
There probably isn't going to be a good answer, since StructureMap is on its way out. I ended up not using StructureMap for consumer configuration:
class BusRegistry : Registry
{
public BusRegistry()
{
For<IBusControl>(new SingletonLifecycle())
.Use(context => Bus.Factory.CreateUsingInMemory(x =>
{
x.ReceiveEndpoint("customer_update_queue", endpointCfg => {
endpointCfg.Consumer<FirstSubscriber>(
GetFirstSubscriberFactoryMethod()
);
endpointCfg.Consumer<SecondSubscriber>(
GetSecondSubscriberFactoryMethod()
);
// etc...
});
}));
Forward<IBusControl, IBus>();
}
}
...though I am using StructureMap to inject dependencies into the consumers.

Need to access instance of service inside HostBuilder configured inside the same HostBuilder().ConfigureServices

Is it possible to access instance of DI configured services inside HostBuilder() configuration?
here is what I meant:
return new HostBuilder()
.UseOrleans((cntx, builder) =>
{
builder.ConfigureApplicationParts(parts =>
{
// This is where I want to access instance of IMyService
// in order to help Orleans builder to configure Orleans properly
}
})
.ConfigureServices(services =>
{
services.AddSingleton<IMyService, MyService>();
})
.RunConsoleAsync();
In case this turns out to be an XY problem, and you are you trying to create some startup task, there is a AddStartupTask extension
return new HostBuilder()
.UseOrleans((cntx, builder) => {
//Add a startup task to be executed when the silo has started.
builder.AddStartupTask((sp, token) => {
// access instance of IMyService
IMyService service = sp.GetRequiredService<IMyService>();
//...use service as needed
return Task.CompletedTask;
});
})
.ConfigureServices(services => {
services.AddSingleton<IMyService, MyService>();
})
.RunConsoleAsync();

Injecting a dependancy INTO Automapper 4.2 Map Profile

my first question that I can't find the exact answer elsewhere.
Using Automapper 4.2.1, Unity 4.01
I'm trying to have an Automapper profile call my service interface again to get a nested object to map to my destination property. Ultimately I would prefer to not use ResolveUsing, but if that works that is fine with me.
public class HeadlineMap : Profile
{
private readonly IDeserializeModels _deserialize;
public HeadlineMap(IDeserializeModels argDeserializeModels)
{
_deserialize = argDeserializeModels;
}
protected override void Configure()
{
CreateMap<LiveSiteHeadline, Headline>().
...
ForMember(t => t.VideoTitle, options => options.MapFrom(f => f.videoTitle)).
ForMember(t => t.Disclaimer, options => options.ResolveUsing<ResolveDisclaimerReference>().ConstructedBy(()=> new ResolveDisclaimerReference(_deserialize)));
}
}
public class ResolveDisclaimerReference : ValueResolver<LiveSiteHeadline, Object>
{
private readonly IDeserializeModels _deserialize;
public ResolveDisclaimerReference(IDeserializeModels argDeserializeModels)
{
_deserialize = argDeserializeModels;
}
protected override object ResolveCore(LiveSiteHeadline source)
{
return _deserialize.GetResponseObject(source.disclaimer.urlPattern, source.disclaimer.project, source.disclaimer.path);
}
}
I'm using the recommended 4.2.1 way of registering all of my maps within the Unity container:
var config = new MapperConfiguration(cfg =>
{
foreach (var profile in profiles)
{
cfg.AddProfile(profile);
}
});
container.RegisterType<MapperConfiguration>(new ContainerControlledLifetimeManager(),
new InjectionFactory(c => config))
.RegisterType<IMapper>(new InjectionFactory(c => c.Resolve<MapperConfiguration>().CreateMapper()));
But when I run the above I get -
"Missing type map configuration or unsupported mapping.".
Any ideas on what I'm missing? The other examples using ObjectFactory, Ninject don't seem to work as I must not be using those.

getServiceLocator() in Service Layer in ZF2?

I created a service layer AbcService in order to allow modules to access common lines of code. But I need to use database to extract values in my AbcService. So, I need to call getAbcTable() which calls $service->getServiceLocator(). When I try this, I get an error saying 'Call to undefined method getServiceLocator().
public function getAbcTable()
{
if (!$this->abcTable) {
$sm = $this->getServiceLocator();
$this->abcTable = $sm->get('Abc\Model\AbcTable');
}
return $this->abcTable;
}
You're trying to call a method that presumably doesn't exist. If you need AbcTable in your service, you should pass it in as a dependency.
Create a factory for your service that does this, in Module.php:
public function getServiceConfig()
{
return array(
'factories' => array(
'AbcService' => function($sm) {
$abcTable = $sm->get('Abc\Model\AbcTable');
$abcService = new AbcService($abcTable);
return $abcService;
},
);
}
and modify the constructor for your service to accept the table as a paramter:
class AbcService
{
protected $abcTable;
public function __construct($abcTable)
{
$this->abcTable = $abcTable;
}
// etc.
}
then, wherever you need AbcService, either inject it in, or grab it from the service locator:
public function indexAction()
{
$abcService = $this->getServiceLocator()->get('AbcService');
}
and the service will have the table class in it.

ZF2 How to get access to the service manager on a custom class that is no a controller, helper or service

guys,
At this point i am close to start pulling hair out of my head. I don't find a way to achieve this.
I have a custom class that belongs to a custom folder i created under my WebServices Module src folder. I need to be able to instantiate this class from inside another module/controller but when i do that and dump the services member it contains null.
How can i have the service manager accesible from inside my ApiAuthentication class.
Any help will be appreciated. Thanks
<?php
namespace WebServices\Services;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class ApiAuthenticationService extends \Zend\Soap\Client implements ServiceLocatorAwareInterface{
public $services;
function __construct($options = null){
parent::__construct('http://tinysoa.local/soap/security/api_authentication?wsdl',$options);
}
public function setServiceLocator(ServiceLocatorInterface $locator)
{
$this->services = $locator;
}
public function getServiceLocator()
{
return $this->services;
}
}
When i call this from inside another module/controller it dumps a null value:
class IndexController extends AbstractActionController
{
public function indexAction()
{
$a = new \WebServices\Services\ApiAuthenticationService();
var_dump($a->services);
Responding with my own answer to add-on to Adrian's, and the question you asked in response.
If your service has dependencies of it's own, you just use a factory instead of going the invokable route.
Say your service needs a cache adapter and database adapter. Also imagine that it can optionally be configured with some other service (FooService, below):
<?php
public function getServiceConfig()
{
return array(
'factories' => array(
'my_service' => function($sm){
$cache = $sm->get('Cache');
$dbAdapter = $sm->get('DefaultDbAdapter');
$fooService = $sm->get('FooService');
// instantiate your service with required dependencies
$mySvc = new \My\Shiny\Service($cache, $dbAdapter);
// inject an optional dependency
$mySvc->setFooService($fooService);
// return your shiny new service
return $mySvc;
}
)
);
}
Side Note: It's generally bad design to inject the ServiceManager all over the place. You're better off managing your dependencies more explicitly, like above.
This stuff is covered quite well in the Quick Start, if you haven't already read that.
Register your Service in Service Config and access it through getServiceLocator() method in controller.
Module.php
public function getServiceConfig()
{
return array(
'invokables' => array(
'my_service' => 'WebServices\Services\ApiAuthenticationService'
)
);
}
Controller
public function indexAction()
{
$service = $this->getServiceLocator()->get('my_service');
}

Resources