NServiceBus Configuration with Custom Container - c#-4.0

I am trying to re-use the service registrations in an assembly that I use through a few services in my solution. I follow the example listed from the NServiceBus website to implement the solution. When following that, unless I add the IWantCustomInitialization interface, my Init method (and IoC container implementation) appears not to function. When I have that interface implemented, I get exceptions (listed in SO questions here and here). I can't seem to get it to work that there are no exceptions AND the dependencies in my MessageHandler are being populated properly. Here is my current EndpointConfig implementation.
[EndpointSLA("00:00:30")]
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, UsingTransport<Msmq>, INeedInitialization {
public void Init() {
Configure.With().ObjectBuilderAdapter();
}
}
public class ObjectBuilderAdapter : IContainer {
readonly IDependencyInjector injector;
public ObjectBuilderAdapter(IDependencyInjectionBuilder dependencyInjectionBuilder) {
injector = dependencyInjectionBuilder.Create(); //This method does all the common service registrations that I am trying to re-use
//injector.RegisterType<ExtractIncomingPrincipal, PrincipalExtractor>();
}
public void Dispose() {
injector.Dispose();
}
public object Build(Type typeToBuild) {
return injector.Resolve(typeToBuild);
}
public IContainer BuildChildContainer() {
return new ObjectBuilderAdapter(new DependencyInjectorBuilder());
}
public IEnumerable<object> BuildAll(Type typeToBuild) {
return injector.ResolveAll(typeToBuild);
}
public void Configure(Type component, DependencyLifecycle dependencyLifecycle) {
injector.RegisterType(component);
}
public void Configure<T>(Func<T> component, DependencyLifecycle dependencyLifecycle) {
injector.RegisterType(component);
}
public void ConfigureProperty(Type component, string property, object value) {
if (injector is AutofacDependencyInjector) {
((AutofacDependencyInjector)injector).ConfigureProperty(component, property, value);
} else {
Debug.WriteLine("Configuring {0} for property {1} but we don't handle this scenario.", component.Name, property);
}
}
public void RegisterSingleton(Type lookupType, object instance) {
injector.RegisterInstance(lookupType, instance);
}
public bool HasComponent(Type componentType) {
return injector.IsRegistered(componentType);
}
public void Release(object instance) { }
}
public static class Extensions {
public static Configure ObjectBuilderAdapter(this Configure config) {
ConfigureCommon.With(config, new ObjectBuilderAdapter(new DependencyInjectorBuilder()));
return config;
}
}
Note: When I use the INeedInitialization interface, I get the ComponentNotRegisteredException when it's looking for IStartableBus.

When you are trying to swap the built in container, then you need to implement IWantCustomInitialization in the same class that implements IConfigureThisEndpoint.
You can use your own container and register all your types in there and tell NSB to use that container.
For example:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
public void Init()
{
var container = new ContainerBuilder().Build();
Configure.With()
.AutofacBuilder(container);
}
}

Related

Registering AutoMapper with Unity fails

I have the following code to register Mapping (version 4.2)
public class ModelMapperProfile : Profile
{
protected override void Configure()
{
CreateMap<Case, CaseModel>();
CreateMap<CaseDetail, CaseDetailModel>();
}
}
public static class AutoMapperService
{
public static MapperConfiguration Initialize()
{
MapperConfiguration config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<ModelMapperProfile>();
});
return config;
}
}
And I register the dependency using unity as follows...
public static void RegisterTypes(IUnityContainer container)
{
container.LoadConfiguration();
var mapper = AutoMapperService.Initialize()
.CreateMapper();
container.RegisterInstance<IMapper>(mapper);
}
My here service constructor..
public TaxLiabilityCaseService(IMapper mapper,
IUnitOfWork unitofWork,
IRepository<Case> caseR,
IRepository<CaseDetail> caseDetailR)
{
_mapper = mapper;
_unitofWork = unitofWork;
_caseR = caseR;
_caseDetailR = caseDetailR;
}
And I get the following error message..
The current type, AutoMapper.IMapper, is an interface and cannot be
constructed. Are you missing a type mapping?
Answers found here did not work for me
What am I missing here
Try following these steps (MVC5):
Get Unity Nuget package:
Unity.Mvc5
Create this class:
public class MapperConfig
{
public static IMapper Mapper { get; set; }
public static void RegisterProfiles()
{
var config = new MapperConfiguration(cfg =>
{
// add profiles here
});
config.AssertConfigurationIsValid();
Mapper = config.CreateMapper();
}
}
In the UnityConfig file (created by the package), add this:
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterInstance<IMapper>(MapperConfig.Mapper);
}
In the Global.asax, add these:
protected void Application_Start()
{
MapperConfig.RegisterProfiles();
UnityConfig.RegisterComponents();
}
You should be good after this.

ninject interception with attribute

I'm trying to use ninject interception in my project for logging exceptions. On the line
public override void Load()
{
this.Bind<IPoShippingRepository>().To<PoShippingRepository>().Intercept().With<ExceptionInterceptor>();
}
I have got an error:
Error loading Ninject component IAdviceFactory
No such component has been registered in the kernel's component container.
Suggestions:
1) If you have created a custom subclass for KernelBase, ensure that you have properly implemented the AddComponents() method.
2) Ensure that you have not removed the component from the container via a call to RemoveAll().
3) Ensure you have not accidentally created more than one kernel.
Ninject initializing is simple:
private static IKernel _kernel;
public UnitOfWork()
{
_kernel = new StandardKernel(new DomainNinjectModule());
}
...
public class DomainNinjectModule : NinjectModule
{
public override void Load()
{
this.Bind<IPoShippingRepository>().To<PoShippingRepository>().Intercept().With<ExceptionInterceptor>();
}
}
class ExceptionInterceptor : IInterceptor
{
private eKindOfLog _kindOfLog;
public ExceptionInterceptor(eKindOfLog kindOfLog)
{
_kindOfLog = kindOfLog;
}
public void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
}
catch (Exception ex)
{
switch (_kindOfLog)
{
case eKindOfLog.Sql:
SimpleLog.LogSqlError(ex);
break;
case eKindOfLog.Error:
SimpleLog.LogSqlError(ex);
break;
}
}
}
}
I installed Ninject.dll, Ninject.Extensions.Interception.dll and Ninject.Extensions.Interception.DynamicProxy.dll.
Method where I used interception attribute is public and virtual.
Please, help what have I done wrong?

Guice - Dynamically selecting provider based on external parameter

In guice, Is there a way to select particular implementation for binding based on some external parameter
Eg:
public interface Service {
void sendMessage()
}
class EmailService implements Service {
public EmailService() { }
#Override
void sendMessage() {
println "Sending email..."
}
}
class SMSService implements Service {
public EmailService() { }
#Override
void sendMessage() {
println "Sending sms..."
}
}
class Client {
private Service service
#Inject
Client(Service service) {
this.service = service
}
public void send() {
service.sendMessage()
}
}
public class ServiceProvider implements Provider<Service> {
Service get() {
return new SMSService() //Select implementation here?
}
}
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Service.class).toProvider(ServiceProvider.class).in(Scopes.SINGLETON)
}
}
public static void main(String...args) {
Injector injector = Guice.createInjector(new MyModule())
Client c = injector.getInstance(Client.class)
c.send()
}
In the above example, I'm forced to select which provider to use in Provider get() method. If I want to make this more dynamic, say for example, based on user preference, is there a way to wait select the provider at runtime and have guice inject it?
For these kind of problems, guice offers the MapBinder:
public class SnacksModule extends AbstractModule {
protected void configure() {
MapBinder<String, Snack> mapbinder
= MapBinder.newMapBinder(binder(), String.class, Snack.class);
mapbinder.addBinding("twix").toInstance(new Twix());
mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
mapbinder.addBinding("skittles").to(Skittles.class);
}
}
With this binding, a Map can now be injected:
class SnackMachine {
#Inject
public SnackMachine(Map<String, Snack> snacks) { ... }
}
You can define all your services in advance, and than pick the concrete instance (or provider) from the map byconfigured value.

ServiceStack's Funq.Container not Newing-Up Properties

My service uses a utility class and that utility class has several public properties. Is there something special I need call to ensure these public properties are setup?
The service uses a ASP.NET host. Inside of Global.ASAX I have declared a new AppHostBase:
public class MyServiceHost : AppHostBase
{
public MyServiceHost() : base("My Service Host", typeof(ServiceLibrary).Assembly) {}
public override void Configure(Funq.Container container)
{
container.Register<IDbConnectionFactory>(dbConFactory);
container.RegisterAutoWired<UtilityLibrary>();
container.RegisterAutoWired<RepositoryLibrary>();
}
}
Within both my repository library and utility library is a main class. This may class receives the Container and registers more specific utilities and repositories:
public class UtilityLibrary
{
public UtilityLibrary(Funq.Container container)
{
container.RegisterAutoWired<WidgetAActions>();
container.RegisterAutoWired<WidgetBActions>();
}
}
In the example below, WidgetARepository was set in the constructor of the RepositoryLibrary class. The RepositoryLibrary class, which contains the WidgetARepository, was supplied to the Container in the Configure method of the AppHost (first snippet above). Even still, the WidgetARepository (below) is never set:
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
public WidgetA Get(string id)
{
var item = this.WidgetARepository.Get(id);
if (item == null) { return null; }
// Do something else
return item;
}
}
Must I manually call Resolve()? This seems like it would defeat the purpose of injection by doing this.
If you are using wanting to use the Funq Container Autowire IoC outside of the ServiceStack service then you need to call Container.AutoWire yourself to have the container inject the relevant dependencies. This call is made behind the scenes in the ServiceStack request pipeline.
For ServiceStack v4:
HostContext.Container.AutoWire(objectToPopulate);
For ServiceStack v3:
AppHostBase.Instance.Container.AutoWire(objectToPopulate);
I would typically add this call to the construtor method of the object I want populated with the injections. So in your case:
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
public WidgetAActions()
{
// (Substitute with v3 usage if required.)
HostContext.Container.AutoWire(this);
}
...
}
Hope this helps.
Edit: Have you considered having the container inject the corresponding repository to WidgetAActions's constructor?
container.RegisterAutoWired<WidgetAActions>(c => new WidgetAActions(c.Resolve<WidgetARepository>()));
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; private set; }
public WidgetAActions(WidgetARepository repository)
{
WidgetARepository = repository;
}
...
}
Edit: Or you could resolve and set the public property of your object to the repository and then you don't have to have a constructor:
container.RegisterAutoWired<WidgetAActions>(c =>
new WidgetAActions { WidgetARepository = c.Resolve<WidgetARepository>() }
);
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
...
}
Or you could call autowire at time of resolving WidgetAActions:
container.RegisterAutoWired<WidgetAActions>(c => {
var actions = new WidgetAActions();
container.AutoWire(actions); // All dependencies injected
return actions;
});
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
...
}

WCF on IIS: Passing data from a ServiceHostFactory to the Service instances

I am having a WCF application hosted on IIS.
I am initializing an IoC container in a custom ServiceHostFactory.
Basically what I would like is to be able to "inject" that IoC Container to each Service instance created within the scope of that ServiceHost.
How would you accomplish that?
Ariel
Like you said you will need a custom ServiceHostFactory that should be used in order to create your services. Something like this:
public class SessionPerCallServiceHostFactory : ServiceHostFactory
{
public SessionPerCallServiceHostFactory()
{
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new SessionPerCallServiceHost(serviceType, baseAddresses);
}
}
You will also need a ServiceHost responsible for creating the necessary service:
public class SessionPerCallServiceHost : ServiceHost
{
public SessionPerCallServiceHost()
{
}
public SessionPerCallServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
}
protected override void OnOpening()
{
Description.Behaviors.Add(new SessionPerCallServiceBehavior());
base.OnOpening();
}
}
With a custom implementation of IServiceBehavior that will be able to provider the InstanceProvider used to create the service instances:
public class SessionPerCallServiceBehavior : IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider =
new SessionPerCallInstanceProvider(serviceDescription.ServiceType);
}
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters)
{
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
And finally the instance provider that will allow you to use the IoC to inject whatever you want in the requested service instance:
public class SessionPerCallInstanceProvider : IInstanceProvider
{
private readonly Type _serviceType;
public SessionPerCallInstanceProvider(Type serviceType)
{
_serviceType = serviceType;
}
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
//I'm creating it without any tricks but you could use your IoC container here
return Activator.CreateInstance(_serviceType);
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public void ReleaseInstance(System.ServiceModel.InstanceContext instanceContext, object instance)
{
}
}
Hope it helps!

Resources