How to access NServiceBus dependency injection container? - nservicebus

I'm using NServiceBus 5's default dependency injection features. I want to register a singleton that depends on IBus in the endpoint config.
Ex:
configuration.RegisterComponents(r =>
{
r.RegisterSingleton(new MyDependency(resolveIBus()));
...
}
How can I resolve the instance of IBus in the above pseduo code using NServiceBus's out-of-the-box dependency injection?

The correct syntax would be:
configuration.RegisterComponents(r =>
{
r.ConfigureComponent<MyDependency>(DependencyLifecycle.SingleInstance);
...
}
The dependency mechanism will investigate the constructor(s) of the MyDependency type and chooses the simplest one it can completely resolve. So, you'll need to create your MyDependency type like this:
public class MyDependency
{
public MyDependency(IBus bus)
{
}
}
More information in the NServiceBus Documentation
If you only know what type of service you need at runtime, you can use the IServiceProvider service like this:
public class MyDependency
{
public MyDependency(IServiceProvider serviceProvider)
{
...
var myService = (IMyService)serviceProvider.GetService(typeof(IMyService));
...
}
}

Related

Simplified approach to IOptions<T>

I am trying to get a .NET Framework class library in line with an ASP.NET Core 2.1 application while using builtin DI mechanism. Now, I created a config class and added appropriate section to appsettings.json:
services.Configure<MyConfig>(Configuration.GetSection("MyConfiguration"));
services.AddScoped<MyService>();
In class lib:
public class MyService
{
private readonly MyConfig _config;
public MyService(IOptions<MyConfig> config)
{
_config = config.Value;
}
}
However, in order to build this classlib I have to add Microsoft.Extensions.Options NuGet package. The problem is that package carries a hell of a lot of dependencies which seem rather excessive to add just for the sake of one interface.
So, the question ultimately is, "is there another approach I can take to configure a DI service located in .NET Framework class library which is not dependency heavy?
Check this article written by Filip Wojcieszyn.
https://www.strathweb.com/2016/09/strongly-typed-configuration-in-asp-net-core-without-ioptionst/
You add extension method:
public static class ServiceCollectionExtensions
{
public static TConfig ConfigurePOCO<TConfig>(this IServiceCollection services, IConfiguration configuration) where TConfig : class, new()
{
if (services == null) throw new ArgumentNullException(nameof(services));
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
var config = new TConfig();
configuration.Bind(config);
services.AddSingleton(config);
return config;
}
}
Apply it in configuration:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.ConfigurePOCO<MySettings>(Configuration.GetSection("MySettings"));
}
And then use it:
public class DummyService
{
public DummyService(MySettings settings)
{
//do stuff
}
}
I bumped into this problem a little while ago, if you can even call it a problem really. I think we all tend to get a little shell-shocked when we see a dependency list like that. But as #Tseng mentioned, it's really not a big deal to include a bunch of extra tiny assemblies (they'll be included in the bin already anyways by virtue of a reference in another project). But I will admit it's annoying to have to include them just for the options interface.
How I solved it was by resolving the service dependency in startup.cs and adjust the service's constructor accordingly:
services.AddTransient<MyService>(Configuration.GetConfiguration("MyConfiguration"));
If you don't care about whatever IOptions provides you, why not just inject IConfiguration into your service?
public class MyService
{
private readonly IConfiguration _config;
public MyService(IConfiguration config)
{
_config = config;
}
public void DoSomething()
{
var value = _config["SomeKey"];
// doing something
}
}

ASP.NET 5 Controller dependency injection of concrete class with no interface in to controller

Is it possible to use StructureMap to scan assemblies to be aware of concrete classes that do not implement interfaces? I am fairly new to StructureMap so not sure if this should be an obvious thing.
For context, below are the highlights of the classes I am working with. UserController depends on an instance of UserManager which depends on an instance of IUserRepository.
public interface IUserRepository { }
public class UserRepository { }
public class UserManager
{
public UserManager(IUserRepository repository) { }
}
public class UserController
{
public UserController(UserManager manager) { }
}
This is the code I have in my Startup.ConfigureServices method to do the scanning for DI:
// Setup dependencies using StructureMap
var container = new Container(x =>
{
x.Scan(s =>
{
s.AssemblyContainingType<UserRepository>();
s.WithDefaultConventions();
});
});
container.Populate(services);
The problem is I get the following error:
Unable to resolve service for type 'UserManager' while attempting to
activate 'UserController'.
If I add the following line to Startup.ConfigureServices then it works, but I am looking for a solution that doesn't require me to have a line for every manager. I have been thinking StructureMap assembly scanning could solve this but I am open to other solutions as well.
services.AddTransient<UserManager>();
Add .AddControllersAsServices() extention method to your services.AddMvc() call.
Result:
services.AddMvc().AddControllersAsServices();

how to access endpoint configuration in a custom NServiceBus profile handler

I'm migrating code from NSBv4 to NSBv5 (5.2.12 to be exact) and I have a custom profile implementation:
public class MyProfileHandler : IHandleProfile<PerformanceCounters>
{
public MyProfileHandler()
{
}
public void ProfileActivated(BusConfiguration config)
{
// I need to do something based on endpoint configuration, e.g. endpoint name
// this used to work in NSBv4:
// var endpointName = Configure.EndpointName;
}
}
How can I access endpoint configuration here?
I'm hosting this app using NServiceBus.Host (v6.0.0 if it matters) and this is where the IHandleProfile<T> interface comes from.
BusConfiguration is a configuration builder and it seems it's not possible to read anything useful from it. I tried to inject an instance of Configure to the constructor of my profile handler, but then it crashes - NSB needs the handler to have a parameterless constructor.
Implementing IWantTheEndpointConfig is not an option as well, as it is deprecated in v5 and it causes a compilation error. Its obsolete error message states:
IHandleProfile is now passed an instance of Configure
(which would be perfect for my case), but this is not true as far as I can tell (there is no Configure passed to ProfileActivated() and I can't see how I can inject it).
Is my only option to reimplement the profile handler using a completely different approach, or am I missing something?
NServiceBus.Core has an issue how it sets the endpoint name (and unfortunately also the endpoint version) on the BusConfiguration. The set endpoint name is added to the settings dictionary too late. You can work around that issue by doing the following:
public class EndpointConfig : IConfigureThisEndpoint
{
public void Customize(BusConfiguration configuration)
{
var customConfig = new EndpointConfiguration
{
EndpointName = "YourEndpointName",
};
configuration.EndpointName(customConfig.EndpointName);
configuration.GetSettings().Set<EndpointConfiguration>(customConfig);
}
}
public class EndpointConfiguration
{
public string EndpointName { get; set; }
}
BusConfiguration is essentially a dictionary on steroids. If you want to get access to what has been set in the BusConfiguration in the profile handler you can do the following (i.ex. get the endpoint name):
public class MyProfileHandler : IHandleProfile<PerformanceCounters>
{
public void ProfileActivated(BusConfiguration config)
{
var customConfig = config.GetSettings().Get<EndpointConfiguration>();
var endpointName = customConfig.EndpointName;
}
}
In the normal NServiceBus Host the interface offers only the one parameter, BusConfiguration. On Azure the interface offers two methods, where one actually has the Configure object.

Implement FluentSecurity 2.0.0 with Ninject MVC

Error activating ISecurityContext using binding from ISecurityContext to SecurityContext.
I'm getting the above error with FluentSecurity 2.0.0 when I'm trying to configure it with Ninject.Web.Mvc3 in an ASP.NET MVC 4 web application.
I think the internal IoC of FluentSecurity and the Ninject IoC may be clashing. Or I may be incorrectly setting up the DependencyResolver in the SecurityConfigurator.
I need to set it up with IoC as I need to get the UserRoles through an injected class.
public static class SecurityConfig
{
public static ISecurityConfiguration Configure()
{
SecurityConfigurator.Configure(
configuration =>
{
configuration.ResolveServicesUsing(
DependencyResolver.Current.GetServices,
DependencyResolver.Current.GetService);
configuration.DefaultPolicyViolationHandlerIs(() => new DefaultPolicyViolationHandler());
configuration.GetAuthenticationStatusFrom(
() => HttpContext.Current.User.Identity.IsAuthenticated);
configuration.GetRolesFrom(
() =>
((IPersonManager)DependencyResolver
.Current
.GetService(typeof(IPersonManager)))
.GetCurrentUserRoles());
configuration.ForAllControllers().DenyAnonymousAccess();
configuration.For<AdminController>().RequireAnyRole(Role.Administrator);
});
return SecurityConfiguration.Current;
}
}
Where am I going wrong? Is there another way I could achieve this?
I faced the same situation. It happened because Ninject throws an exception when cannot resolve a dependency. I solved it implementing my own ISecurityServiceLocator
public class FluentSecurityServiceLocator : ISecurityServiceLocator
{
public static IKernel Kernel { get; set; }
public object Resolve(Type typeToResolve)
{
return Kernel.TryGet(typeToResolve);
}
public IEnumerable<object> ResolveAll(Type typeToResolve)
{
if (!Kernel.GetBindings(typeToResolve).Any())
{
return new List<object>();
}
return Kernel.GetAll(typeToResolve);
}
}
I passed the kernel instance in my ninject configuration class
FluentSecurityServiceLocator.Kernel = kernel;
Hope this helps!
I'm not really familiar with Ninject but are you sure that DependencyResolver.Current.GetServices and DependencyResolver.Current.GetService won't throw an exception when FluentSecurity asks for something (like ISecurityContext) that is not registered with Ninject?
In structuremap there is a method called TryGetInstance that won't throw an exception when asking for something that is not registered in the container. You can read more on how FluentSecurity and IoC works here:
https://github.com/kristofferahl/FluentSecurity/wiki/IoC-container-integration

Ninject property binding, how to do correctly

I have installed Ninject (v4.0.30319) package in test project to test. Create test code below, unfortunately ValidateAbuse.Instance.Repository is always Null. Why Ninject do not bind repository to ValidateAbuse.Repository property?
Some of you may suggest to use constructor binding but I can't use it due to code structure. The below code is just example and I need to find a way to bind to property.
Test method which always fail
[TestMethod]
public void PropertyInjection()
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<ISettingsRepository>().To<SettingsRepository>();
Assert.IsNotNull(ValidateAbuse.Instance.Repository);
}
}
The repository interface
public interface ISettingsRepository
{
List<string> GetIpAbuseList();
List<string> GetSourceAbuseList();
}
The repository implementation
public class SettingsRepository : ISettingsRepository
{
public List<string> GetIpAbuseList()
{
return DataAccess.Instance.Abuses.Where(p => p.TypeId == 1).Select(p => p.Source).ToList();
}
public List<string> GetSourceAbuseList()
{
return DataAccess.Instance.Abuses.Where(p => p.TypeId == 2).Select(p => p.Source).ToList();
}
}
The class to which I am trying to bind repository
public class ValidateAbuse
{
[Inject]
public ISettingsRepository Repository { get; set; }
public static ValidateAbuse Instance = new ValidateAbuse();
}
Ninject will only bind properties on an object when it creates an instance of that object. Since you are creating the instance of ValidateAbuse rather than Ninject creating it, it won't know anything about it and therefore be unable to set the property values upon creation.
EDIT:
You should remove the static singleton from ValidateAbuse and allow Ninject to manage it as a singleton.
kernel.Bind<ValidateAbuse>().ToSelf().InSingletonScope();
Then when you ask Ninject to create any class that needs an instance of ValidateAbuse, it will always get the same instance.
It seems like you don't fully understand how Ninject works or how to implement it so I would suggest you read the wiki https://github.com/ninject/ninject/wiki/How-Injection-Works and follow some more basic examples before trying to wire it into an existing application.