I'm building an application that performs actions initiated by a user and one particular class has dependencies on things I can wire up in DI such as an ILogger instance as well as an HttpClient in addition to runtime arguments that identify the user and the instance of the action (mostly to be used while logging to help with debugging).
The trouble I have is that I'm not entirely sure how to inject this class into the other classes that need it as a result of the runtime dependencies.
Here's a simplified example of one of my classes:
public class Dependency : IDependency
{
private readonly HttpClient httpClient;
private readonly ILogger<Dependency> logger;
private readonly RuntimeDeps runtimeDeps
public Dependency(
ILogger<Dependency> logger,
HttpClient httpClient,
RuntimeDeps runtimeDeps)
{
// set private fields
}
public Result DoStuff()
{
// use Http client to talk to external API
// something fails so log the failure and some helpful info
logger.log($"{runtimeDeps.InstanceId} failed. " +
"Initiated by {runtimeDeps.UserName}");
}
}
This feels like it requires a factory to create but then is it best to request the HttpClient and Logger in the factory method or declare it as a dependency of the factory? If the latter, I presume the factory would have to be registered as a transient or as a scoped resource since registering it as a singleton would result in a captive dependency (I think).
Any suggestions on redesigns are also welcome if this is a symptom of a poor design. I'd love to implement Mark Seeman's Pure DI to get some more assistance from the compiler but I don't know if that's possible in Azure functions.
A transient factory with the transient dependencies injected into the constructor and the runtime dependencies as parameters of the Create method will work fine.
DI is baked into the Azure Functions library in the sense that parameters are injected into the trigger methods, but beyond these you should be able to use Pure DI to manage your own dependencies by calling into some composition root helper class from the trigger function which knows how to build your dependency graph in a pure manner.
Instead of requiring runtime data during the construction of a component, it's better to let runtime data flow through method calls on an initialized object graph by either:
passing runtime data through method calls of the API or
retrieving runtime data from specific abstractions that allow resolving runtime data.
I formalized this in 2015 in this blog post, which I referred to in the comments.
After reading your additional comments, I came to the conclusion that in your case option 2 is most suited, as the data you are sending is likely an implementation detail to the component, and should not be part of the public API.
In that case, you can redesign your component as follows:
public class Dependency : IDependency
{
public Dependency(
ILogger<Dependency> logger,
HttpClient httpClient,
IRuntimeDepsProvider provider) ...
public Result DoStuff()
{
// use Http client to talk to external API
// something fails so log the failure and some helpful info
logger.log($"{provider.InstanceId} failed. " +
$"Initiated by {provider.UserName}");
}
}
IRuntimeDepsProvider is an abstraction that hides the retrieval and storage of runtime data. This gives you the ability to postpone the decision to either use a Closure Composition Model or an Ambient Composition Model until the Last Responsible Moment.
Using the IRuntimeDepsProvider abstraction, you can chose to set the incoming runtime values after the object graph is constructed. For instance:
public class MyFunction
{
// Notice the different abstraction here
public MyFunction(
IRuntimeDepsInitializer initializer,
IHandler<Something> handler) ...
public void TheFunction(Guid instanceId, string userName, Something cmd)
{
// Setting the runtime data *after* the object graph is constructed,
initializer.SetData(instanceId, userName);
// but before the graph's public methods are invoked.
handler.Handle(cmd);
}
}
Here, a second abstraction is introduced, namely IRuntimeDepsInitializer. Now you can have one class implementing both interfaces:
public class RuntimeDepsStorage : IRuntimeDepsInitializer, IRuntimeDepsProvider
{
public Guid InstanceId { get; private set; }
public string UserName { get; private set; }
public void SetData(Guid id, string name)
{
InstanceId = id;
UserName = name;
}
}
TIP: Instead of using two interfaces, you can also use only IRuntimeDepsProvider and let MyFunction depend on the concrete RuntimeDepsStorage. Which solution is best depends on the context.
Now the main trick here is to make sure that RuntimeDepsStorage becomes a Scoped dependency, because you want to reuse it throughout a request, but not shared by multiple requests.
When applying Pure DI, this would look like this:
var storage = new RuntimeDepsStorage();
new MyFuncion(
initializer: storage,
handler: new SomethingHandler(
stuffDoer: new Dependency(
httpClient: client, // Did you notice this is a runtime dep as well?
logger: new Logger<Dependency>(),
provider: storage)))
If, on the other hand, you would be using MS.DI as your DI Container, registration would be similar to the following:
services.AddScoped(_ => new RuntimeDepsStorage());
services.AddScoped<IRuntimeDepsProvider>(
c => c.GetRequiredService<RuntimeDepsStorage>());
services.AddScoped<IRuntimeDepsInitializer>(
c => c.GetRequiredService<RuntimeDepsStorage>());
// etc, your usual registrations here
Related
I have an n-tier web application with a Web UserInterface, BusinessLogicLayer and DataAccessLayer. I am looking for the best possible solution to pass my current logged in user's details all the way to the data-access without add it to all my method signatures. The user details are needed for auditing purposes. I believe you can create a context that is available application wide, is there anyone with an example of doing this? I am looking for the best design pattern that will separate my concerns.
Here are two approaches:
First
This approach makes more sense if those other layers actually need to know about the user. For example, they might check permissions or make some decision based on who the user is.
You can create an abstraction or interface to describe what you want those classes to be able to access, something like this:
public interface IUserContext
{
SomeClassContainingUserData GetCurrentUser();
}
I'd define that user data class according to what the consumer class needs instead of just using some existing Customer class just to keep this from getting tightly coupled to your web app.
Now you can inject that class into your other classes:
public class MyBusinessLogicClass
{
private readonly IUserContext _userContext;
public MyBusinessLogicClass(IUserContext userContext)
{
_userContext = userContext;
}
public void SomeOtherMethod(Whatever whatever)
{
var user = _userContext.GetCurrentUser();
// do whatever you need to with that user
}
}
This keeps your other classes testable because it's easy to inject a mock of the interface that returns what you want so you can make sure your class behaves correctly for different types of users.
If your user data comes from HttpContext then your runtime implementation could look roughly like this:
public class HttpUserContext
{
private readonly IHttpContextAccessor _contextAccessor;
public HttpUserContext(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public SomeClassContainingUserData GetCurrentUser()
{
var httpContext = _contextAccessor.HttpContext;
// get the user data from the context and return it.
}
}
That's a rough outline. One consideration is scoping. If all of your objects are scoped per-request then the IUserContext implementation could generate the user data once and store it in a member variable instead of accessing it over and over.
The drawback is having to inject this everywhere, but that's inevitable if those classes need that information.
Second
What if those inner classes don't actually need user information at all? What if you just want to log which users made requests that were handled by those classes? What if you want a separate object to check permissions?
In that case an option would be an interceptor or a wrapper. In its simplest form it could look like this:
public class SomeBusinessClassSecurityInterceptor : ISomeBusinessClass
{
private readonly ISomeBusinessClass _inner;
private readonly IUserContext _userContext;
public SomeBusinessClassSecurityInterceptor(
ISomeBusinessClass inner, IUserContext userContext)
{
_inner = inner;
_userContext = userContext;
}
public void UpdateSomeData(Foo data)
{
if(!CanUpdate())
throw new YouCantUpdateThisException();
_inner.UpdateSomeData(data);
}
private bool CanUpdate()
{
var user = _userContext.GetCurrentUser();
// make some decision based on the user
}
}
If retrieving permissions for a user is more involved, you might want to have an IUserPermissions and inject that instead of IUserContext. Then inject IUserContext into the implemenation of IUserPermissions. At runtime it retrieves the current user and then does its own thing to determine what permissions the user has.
If you've got lots of classes and methods then maintaining separate wrapper classes could become tedious. Another option is to use an interceptor which likely means using a different dependency injection container like Windsor or Autofac. These are especially good for logging.
Using Autofac as an example, that would mean writing a class like this:
public class LoggingInterceptor : IInterceptor
{
private readonly IUserContext _userContext;
private readonly ILogger _logger;
public CallLogger(IUserContext userContext, ILogger logger)
{
_userContext = userContext;
_logger = logger;
}
public void Intercept(IInvocation invocation)
{
var user = _userContext.GetCurrentUser();
_logger.Log(
// some stuff about the invocation, like method name and maybe parameters)
// and who the user was.
// Or if you were checking permissions you could throw an exception here.
invocation.Proceed();
}
}
Then you would tell the container that all calls to the "real" implementation of a given class go through this interceptor (described very well in their documentation.)
If you were checking permissions you could inject IUserPermissions. The interceptor could check for an attribute on the inner method that specifies what permissions are needed and compare that to the current user's permissions.
You can typically write one interceptor and use it with lots of other classes because it doesn't need to know anything about the inner target class. But if you need to you can also write more narrowly-purposed interceptors used just for certain classes.
What's nice is that it gives you a lot of flexibility but doesn't touch the actual interface or implementation of your business logic or data classes. They can focus on their single responsibilities while other classes are configured to log requests made to them or check user permissions.
I'm not sure what is the best way to achieve what I am trying to accomplish so let me give you an example.
I am using Azure Functions, which are stateless, with the following signature.
public static Task Run(Message message, ILogger logger)
{
var controller = Main.Container.GetInstance<ConsumerController>();
// How can I attach the passed in logger instance so the rest of
// the services for the current flow re-use this instance?
return controller.Execute(message);
}
As you can see, the azure function framework passes me an instance of the ILogger already configured and initialized for this function call only.
I read through the documentation and I think I need a new scope here but I'm not sure. I only want this ILogger instance to be used during the async execution of this one method call. Each function call will use their own.
And just to be clear, the controller is only one of possibly many services (services, repositories, request handlers) involved in the execution of the task.
Any help would be great?
You can do the following:
Create a Proxy (e.g. ProxyLogger) implementation that implements ILogger, contains a ILogger Logger property, and forwards any call to that property.
Register that Proxy both as ILogger and ProxyLogger as Lifestyle.Scoped.
Resolve ProxyLogger within your function.
Set ProxyLogger.Logger using the function's supplied ILogger.
Resolve the root object and use it.
Create a Proxy:
public class ProxyLogger : ILogger
{
public ILogger Logger { get; set; }
public void Log<TState>(LogLevel l, EventId id, TState s, Exception ex,
Func<TState,Exception,String> f) =>
this.Logger.Log<TState>(l, id, s, ex, f);
// Implement other functions
}
Register that Proxy:
container.Register<ProxyLogger>(Lifestyle.Scoped);
container.Register<ILogger, ProxyLogger>(Lifestyle.Scoped);
Resolve ProxyLogger within your function, set ProxyLogger.Logger using the function's supplied ILogger, and resolve the root object and use it.
public static Task Run(Message message, ILogger logger)
{
using (AsyncScopedLifestyle.BeginScope(Main.Container)
{
Main.Container.GetInstance<ProxyLogger>().Logger = logger;
var controller = Main.Container.GetInstance<ConsumerController>();
return controller.Execute(message);
}
}
I do think, however, that this model leads to a very large amount of infrastructural code. Preferably you wish to keep this infrastructure to the absolute minimum. Instead, you could try keeping your Azure Functions small Humble Objects, as described here. That might not completely solve your initial problem, but you might not need to have a method specific logger anyway. But if, on the other hand, you need that, you might be able to mix that Humble Object approach with the use of C#'s CallerMemberName attribute and the ProxyLogger approach. You don't really need the Azure injected ILogger to do that for you.
I am trying to set up a new project and I've added a new class MembershipService that requires the HttpContext to be passed in it's constructor.
In a previous project I used the code
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IMembershipService>()
.To<MembershipService>()
.InRequestScope()
.WithConstructorArgument("context", HttpContext.Current);
....
}
However in the new project I'm using Ninject Modules, and after some searching on StackOverflow and Google, I've come up with the code below:
public class ServiceHandlerModule : NinjectModule
{
public override void Load()
{
Bind<IMembershipService>()
.To<MembershipService>()
.WithConstructorArgument("context", ninjectContext=> HttpContext.Current);
this.Kernel.Bind(x =>
{
x.FromAssemblyContaining(typeof(NinjectWebCommon))
.SelectAllClasses()
.Where(t => t != typeof(MembershipService))
.BindDefaultInterface();
});
this.Kernel.Bind(x =>
{
x.FromAssemblyContaining<BrandServiceHandler>()
.SelectAllClasses()
.Where(t => t != typeof(MembershipService))
.BindDefaultInterface();
});
}
}
However, I get the error below:
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: Ninject.ActivationException: Error activating
string No matching bindings are available, and the type is not
self-bindable. Activation path:
5) Injection of dependency string into parameter filename of
constructor of type HttpRequest
4) Injection of dependency HttpRequest into parameter request of
constructor of type HttpContext
3) Injection of dependency HttpContext into parameter httpContext of
constructor of type MembershipService
2) Injection of dependency IMembershipService into parameter
membershipService of constructor of type HomeController
1) Request for HomeController
Can someone point out where I'm going wrong?
Thanks,
John
Steven was right about the HttpContext being a runtime value. Its values are not even populated at the time the application is composed.
This makes sense if you think about it because the application should be initialized outside of any individual user context.
However, Steven's solution only moved the problem to a different service. After all, the class that implements IUserContext will still need to take HttpContext as a dependency.
The solution is to use an Abstract Factory to allow the HttpContext instance to be accessed at runtime instead of when the factory is wired up.
Important: HttpContext is not an abstraction, so it cannot be swapped or mocked. To ensure we are dealing with an abstraction, Microsoft has provided the HttpContextBase abstract class and the default concrete type HttpContextWrapper. HttpContextBase has exactly the same interface as HttpContext. You should always use HttpContextBase as the abstract reference type within your services, not HttpContext.
With those 2 things in mind, you can create a factory for your HttpContext, as follows:
public interface IHttpContextFactory
{
HttpContextBase Create();
}
public class HttpContextFactory
: IHttpContextFactory
{
public HttpContextBase Create()
{
return new HttpContextWrapper(HttpContext.Current);
}
}
Your MembershipService can then be modified to accept an IHttpContextFactory in its constructor:
public class MembershipService : IMembershipService
{
private readonly IHttpContextFactory httpContextFactory;
// This is called at application startup, but note that it
// does nothing except get our service(s) ready for runtime.
// It does not actually use the service.
public MembershipService(IHttpContextFactory httpContextFactory)
{
if (httpContextFactory == null)
throw new ArgumentNullException("httpContextFactory");
this.httpContextFactory = httpContextFactory;
}
// Make sure this is not called from any service constructor
// that is called at application startup.
public void DoSomething()
{
HttpContextBase httpContext = this.httpContextFactory.Create();
// Do something with HttpContext (at runtime)
}
}
And you need only inject the HttpContextFactory at composition time.
kernel.Bind<IHttpContextFactory>()
.To<HttpContextFactory>();
kernel.Bind<IMembershipService>()
.To<MembershipService>();
This alone might not solve the entire issue, though. You need to ensure that the rest of your application does not try to use HttpContext before it is ready. In terms of DI, it means you can't use HttpContext in any constructor of types that are composed in application start or any service members that one of those constructors calls. To solve that, you may need to create additional abstract factories to ensure those services don't call members of IMembershipService until HttpContext is ready.
See this answer for more information about how to accomplish that.
Steven's solution also entailed creating a Facade around HttpContext. While this does not really help solve the problem at hand, I agree that this might be a good idea if your MembershipService (and perhaps other services) only uses a small number of members of HttpContext. Generally, this pattern is to make a complex object simpler to work with (such as flattening it down to a few members that may be nested deep within its hierarchy). But you really need to weigh the extra maintenance of adding another type against the complexity of using HttpContext within your application (or the value of swapping out a section of it) to make that decision.
I've added a new class MembershipService that requires the HttpContext
to be passed in it's constructor.
This is where you're going wrong. The HttpContext is a runtime value, but your object graph should only consist of compile-time or configuration-time dependencies. Anything else, the runtime values, should either be passed through method calls, or should be exposed as properties from the services that are injected.
Not following this guideline, will make it much harder to compose and test your object graphs. Testing your composition root is a good example, since HttpContext.Current is not available when run inside a testing framework.
So prevent this MembershipService from taking a constructor dependency on HttpContext. Instead, inject a service that exposes the HttpContext as a property, because this allows you to request this context after the object graph is constructor.
But perhaps even better is to hide the HttpContext behind an abstraction that is application specific. HttpContext is not an abstraction; it is a big and ugly API that makes your code much harder to test and much harder to comprehend. Instead, create very narrow/focused interfaces, for instance an interface like this:
public interface IUserContext
{
User CurrentUser { get; }
}
Now your MembershipService can depend on a IUserContext that exposes a User object through a property. Now you can create an AspNetUserContext implementation that uses the HttpContext.Current internally, when the CurrentUser property is called. This results in much cleaner, more maintainable code.
Here's a possible implementation:
public class AspNetUserContext : IUserContext
{
public User CurrentUser
{
// Do not inject HttpContext in the ctor, but use it
// here in this property
get { return new User(HttpContext.Current.User); }
}
}
I agree with Steven, however, you could also:
kernel.Bind<HttpContext>().ToMethod(c => HttpContext.Current);
I am currently trying to get my head around structuremap now that the ObjectFactory static function has been marked as obsolete.
In the long run I have to use this in a MVC and WebApi application. When previously used, a line to a static method was placed in the the global.asax to initialise everything using the ObjectFactory.
ObjectFactory.Initialize{
container.For .....
}
Trying to convert this to the new IContainer approach I have come up with the following however am wondering if I have actually inadvertently implemented this often mentioned Anti-Pattern in my approach.
Static method to return container:
public class StructureMapConfig
{
public static IContainer GetContainer()
{
return new Container(container =>
{
container.For<IUserService>().Use<UserService>();
container.For<IStringService>().Use<StringService>();
container.For<IUserRepository>().Use<UserRepository>();
});
}
}
Userservice's contstructor looks like this:
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
private readonly IStringService _stringService;
public UserService(IUserRepository userRepository, IStringService stringService)
{
_userRepository = userRepository;
_stringService = stringService;
}
Finally the initialise (this instance in a console app) looks somthing like this:
private static IUserService _userService;
private static IContainer _container;
static void Main(string[] args)
{
_container = StructureMapConfig.GetContainer();
_userService = _container.GetInstance<IUserService>();
}
So to my questions.
Am I doing anything seriously wrong here
In the UserService, should I be passing the IContainer in and using the object factory to get the instance or should I leave as is.
Is returning the IContainer from the static method the best approach
If this was a MVC app, is it best practice to build this once in the Global.asax or should the controller constructor call the static method every time.
Thanks for any advice.
To go through your questions in order:
Am I doing anything seriously wrong here
No, I don't see anything seriously wrong here. There are a few improvements you could make that I'll talk about shortly.
In the UserService, should I be passing the IContainer in and using
the object factory to get the instance or should I leave as is.
You're correct in injecting UserService over an instance of IContainer. If your controller only requires the UserService then why inject the entire container. Really you only want to inject the bare minimum of what you need to reduce unnecessary coupling and dependencies.
Is returning the IContainer from the static method the best approach
Within the removal of the ObjectFactory then yes, returning an instance of the container via a static method is a common approach for those classes whose creation is not managed via MVC's Dependency Resolution.
If this was a MVC app, is it best practice to build this once in the
Global.asax or should the controller constructor call the static
method every time.
Creating the container in Global.asax.cs is your best approach as it's done once on Application_Start, however see below for my recommendation of using a nested container per http request.
Improvements:-
Take advantage of StructureMap's registries:
Instead of referencing the dependencies directly like this:
public static IContainer GetContainer()
{
return new Container(container =>
{
container.For<IUserService>().Use<UserService>();
container.For<IStringService>().Use<StringService>();
container.For<IUserRepository>().Use<UserRepository>();
});
}
Opt to use StructureMap's registries instead. This way you can group your dependencies (such as MVC specific dependencies or WebAPI specific dependencies, like so:
public class WebsiteRegistry : Registry
{
public WebsiteRegistry()
{
this.For<IUserService>().Use<UserService>();
this.For<IStringService>().Use<StringService>();
this.For<IUserRepository>().Use<UserRepository>();
}
}
Then load your registries like this:
container.Configure(c => {
c.IncludeRegistry<WebsiteRegistry>();
c.IncludeRegistry<TaskRegistry>();
});
HTTP Context bound containers:
Another recommended pattern when using StructureMap with ASP.NET MVC or WebApi (or any HTTP based application) is to use nested containers that are bound to each HTTP request. This basically involves creating a new nested container on each HTTP request and then disposing it at the end of the request. This ensures that dependencies such as session objects, database connections, or UoW contexts are disposed of as soon as the HTTP request is over.
I would recommend taking a look over this article which goes into more detail on the matter and talks about how this can be set up.
This is exactly the same technique that's used in the StructureMap.MVC5 package that's often recommended by StructureMap's creator, Jeremy Miller.
Auto registering dependencies
Instead of registering every dependency with StructureMap manually you can take advantage of StructureMap's auto-registration. You can also specify your own scanning conventions.
I've recently started using Unity for dependency injections in .net.
I was under the impression that a Unity Container would most likely be a singleton or static member of a class. I saw another developer using it in a request handler that will receive a lot of traffic.
Is there some magic happening that keeps the cost low for creating a new Unity Container every time, or should this code be re-factored to only create the Unity container once?
This code is part of the implementing class of a .svc Service.
public string DoSomeWork(Request request)
{
var container = new UnityContainer().LoadConfiguration("MyContainer");
var handler = container.Resolve<RequestHandler>();
return handler.Handle(request);
}
Not 100% sure with Unity, but with most IoC containers, the creation of the container and especially the loading of container configuration is a reasonably expensive operation.
I have to question why this developer is utilizing the container in this manner however. Ideally the IoC container shouldn't even be a static or singleton object - it should be instantiated only to resolve the top level object of your dependency tree, and the rest of the objects in your application should be constructed automatically through dependency injection. In the case of your example, the class containing that method ideally would have the RequestHandler (ideally an interface of this) injected into it through the constructor so that class does not need to know about the IoC container.
This is not the right way to use an IOC container - basically your are using it as a service locator, but this will cause dependencies to the IOC container to be sprinkled all over the code base.
What you should do is have one central spot in your codebase where all dependencies are resolved and then use dependency injection (DI) to propagate the resolved concrete classes down the chain, i.e via constructor injection. So your class really should look something like this:
public class Foo
{
private readonly IRequestHandler _handler;
public Foo(IRequestHandler handler)
{
_handler = handler;
}
public string DoSomeWork(Request request)
{
return _handler.Handle(request);
}
}