How to determine which constructor Autofac uses when resolving - c#

I'm using a custom JsonConverter and JsonSerializerSettings.TypeNameHandling = TypeNameHandling.Objects to create the required instances during deserialization. The instances are created by resolving the types from an Autofac IOC container. Everything works fine, except...
I have several "core objects" that request a unique Id in the constructor from a service (which is correctly injected into the constructor). When deserializing this should not happen because it is fairly expensive and the Ids will be populated from the Json file anyway once the instance has been created.
Currently, when resolving from within the custom JsonConverter I'm using _scope.Resolve<T>(new TypedParameter(typeof(IIdService), null)); to then - in the called constructor - check for null and act accordingly.
Some people apparently consider multiple constructors worse than a code-smell when using an IOC (which makes me wonder why Autofac offers several features regarding the topic), but in the context of deserialization I think it can make perfect sense.
As far as I can tell Autofac has mechanisms to decide which constructor to use during registration, but not when resolving. My preferred solution would be to add a custom attribute to a constructor (e.g. [CtorForDeserializing]) and use that for deciding. Is that possible?

There are a couple of extension points Autofac has for reflection-based activations but doesn't have well documented yet that may help you out: IConstructorFinder and IConstructorSelector.
IConstructorFinder is used to locate all the available constructors on a type. The core example is the DefaultConstructorFinder which locates only public constructors. If you wanted to, say, hide constructors with particular attributes or start finding internal/private constructors, you could create a custom finder. This really only happens once so you don't get to make runtime choices here.
IConstructorSelector is used to choose, at resolve time, which constructor should be used to instantiate the object. There are a couple of these in core Autofac, but the primary example is the MostParametersConstructorSelector which selects the constructor that has the most available matching parameters at the time. Constructors get found by the IConstructorFinder and then that set of constructors is what is presented to the IConstructorSelector to choose from. This is where you could make more runtime choices since it happens every time the object is resolved.
There are extension methods to help you add your finder/selector to a registration:
builder.RegisterType<MyType>()
.FindConstructorsWith(new MyConstructorFinder())
.UsingConstructor(new MyConstructorSelector());
You don't have to customize both things, you can just do one or the other if you want. I'm just showing you the extensions.

Actually Autofac is able to decide which constructor to use both ways - during registration or resolution. For resolution part here is the quote from documentation: "Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container" (see here).
Consider following example.
public interface ISomeService
{
Guid Id { get; }
}
public class SomeService : ISomeService
{
public Guid Id { get; }
public SomeService()
{
Id = Guid.NewGuid();
}
public SomeService(Guid id)
{
Id = id;
}
}
// Startup.cs:
builder.RegisterType<SomeService>().As<ISomeService>().InstancePerLifetimeScope();
// TestController.cs:
[Route("api/[controller]")]
public class TestController : Controller
{
private readonly IComponentContext _context;
public TestController(IComponentContext context)
{
_context = context;
}
[HttpGet]
public IActionResult Get()
{
var service = _context.Resolve<ISomeService>();
return Ok(service.Id);
}
[HttpGet("{id}")]
public IActionResult Get(Guid id)
{
var service = _context.Resolve<ISomeService>(new NamedParameter("id", id));
return Ok(service.Id);
}
}
// GET http://localhost:5000/api/test/e0198f72-6337-4880-b608-68935122cdea
// each and every response will be the same: e0198f72-6337-4880-b608-68935122cdea
// GET http://localhost:5000/api/test
// this way it responds with some random guid each time endpoint is called

Travis Illig sent me in the right direction - thanks!
I ended up implementing a solution around the following details:
Implement custom attributes, e.g.: public class DeserializeCtorAttribute : Attribute { }, which will be used by the (also to be implemented) IConstructorFinder.
Implement an empty generic interface, e.g.: IDeserializable<T>, which will be used for resolving the services/components.
Let relevant component classes implement the interface (MyClass : IDeserializable<MyClass>) and add an extra registration for the component:
_builder.RegisterType<MyClass>().As<IDeserializable<MyClass>>()
.FindConstructorsWith(MyConstructorFinder);
Use the implemented DeserializeCtorAttribute in the desired constructor of MyClass.
Let the JsonConverter create the required instance by calling (MyClass) scope.Resolve(IDeserializable<MyClass>); casting is required, but safe. Due to the registration the instance will be created using the desired constructor.

Related

Dependency injection in custom attribute in .Net Core [duplicate]

I am trying to inject a dependency into a custom AuthorizeAttribute as follows:
public class UserCanAccessArea : AuthorizeAttribute
{
readonly IPermissionService permissionService;
public UserCanAccessArea() :
this(DependencyResolver.Current.GetService<IPermissionService>()) { }
public UserCanAccessArea(IPermissionService permissionService)
{
this.permissionService = permissionService;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
string AreaID =
httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string;
bool isAuthorized = false;
if (base.AuthorizeCore(httpContext))
isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User);
return isAuthorized;
}
}
This works but seems to be resolving as a singleton meaning I get the problems described in my pervious question
What I'd like to do is use property injection but as my Attribute itself is not resolved by Unity I'm unable to find a way to configure the container to intercept and resolve a property. I have tried the following:
public class UserCanAccessArea : AuthorizeAttribute
{
public IPermissionService permissionService { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
string AreaID =
httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string;
bool isAuthorized = false;
if (base.AuthorizeCore(httpContext))
isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User);
return isAuthorized;
}
}
Container:
container.RegisterType<UserCanAccessArea>(new InjectionProperty("permissionService"));
But the property is always null at runtime.
Has anyone achieved this and if so do you have an example?
You should prevent doing dependency injection into attributes completely. The reason for this is explained in this article: Dependency Injection in Attributes: don’t do it!. In summary the article explains that:
Constructor injection is not possible, because creation of an Attribute instance cannot be intercepted; the CLR is in control.
The use of property injection is fragile, since it results in Temporal Coupling, which should be prevented.
Dependency injection into attributes makes it impossible to verify
the correctness of the container's configuration.
Frameworks like MVC and Web API cache attributes, making it very easy to accidentally create captive dependencies causing bugs.
You have two choices here:
Make the attributes passive, by splitting the data (the attribute) from its behavior (the service) as explained in the referenced article and this related article from Mark Seemann.
Turn your attributes into humble objects as explained in this answer. This means you:
extract all logic from the attribute into a custom service that contains all dependencies.
Register that service in your container.
let the attribute's method (AuthorizeCore in your case) do nothing more than resolving the service from the service locator / DependencyResolver and call the service's method. Important to note here is that you cannot do constructor injection, property injection and the service cannot be stored in the attributes private state (as you already noticed).
Which option to use:
Use option 1 if you are very keen into keeping your design clean, or you have more than a few attributes that you need to apply this way, or you want to apply attributes are defined in an assembly that doesn't depend on System.Web.Mvc.
Use option 2 otherwise.
In ASP.NET Core, this is now possible by either creating a custom attribute, implementing IFilterFactory, or by using TypeFilterAttribute, as well as ServiceFilterAttribute.
Both implement IFilterFactory and do what you'd normally do in your custom attribute implementing IFilterFactory, the only difference is that they support ordering (which you can add if you wish in your custom attribute).
But more specifically - ServiceFilterAttribute gets the instance of your filter from the actual service collection, which allows you to define a specific lifetime to it, whereas TypeFilterAttribute does not use the service collection to create your object, it uses Microsoft.Extensions.DependencyInjection.ObjectFactory which is the result of CreateFactory method. (Basically it creates your object with a lot of expression trees.) TypeFilterAttribute also allows you to pass arguments for non-service constructor parameters. Both use the service collection for any DI.
For your existing codebase you can quite simply do any of the following to achieve Dependency injection in the constructor of an attribute:
[TypeFilter(typeof(MyExistingFilterWithConstructorDI))]
[TypeFilter(typeof(MyExistingFilterWithConstructorDIAndParams), Arguments = new object[] { "first non-service param", "second non-service param" })]
[ServiceFilter(typeof(MyExistingFilterWithConstructorDI)) (you will need to register your filter into the service collection with an appropriate lifetime)
Now, as far as performance goes, if you end up using TypeFilterAttribute, the type for your filter will be created as mentioned above, with expression trees, whereas if you simply create your own IFilterFactory, you control that part, i.e you simply instantiate your object, and for any dependency injection needs - you use the provided IServiceProvider as part of the CreateInstance method for the interface.
The IsReusable property, as part of the IFilterFactory interface is there for you to show if you prefer the framework to use your object outside of the request scope. This, in no way guarantees that you'll ever be stuck with a single object for your filter.
I implemented it like this:
public class ClaimsHandlerAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var jwtAuthManager =
context.HttpContext.RequestServices.GetService(typeof(IJwtAuthManager))
as JwtAuthManager;
return;
}
}

Is it possible to have some kind of dynamic KeyFilter in autofac?

KeyFilter used in Autofac is helpful but really I think it's not dynamic because the key here is preset/setup/defined and attached to constructor parameters at compile time. No way to have something similar working at runtime.
Here is the scenario, at the time resolving for some instance, the key can be determined (which can change dynamically based on the current context). That key then should be taken into account before resolving for the instance. I think Multitenant feature supported by autofac is something very close to that requirement. However I don't think it can be easily used and supports constructor injection (we may have to always create a scope and resolve for instances explicitly and manually, which looks much like a service locator's way).
So applied that imaginary feature in code version picking example, let's see how helpful it can be. Suppose I have 2 implementations for a same interface, each corresponds to one code version (v1 and v2). Now the constructor consuming that interface does not care about which version, but the context will provide the IoC container which version so that it should resolve for the correct implementation corresponding to the that version.
public interface ISender {
void Send(string msg);
}
//version v1
public class SlowSender : ISender {
//...
}
//version v2
public class FastSender : ISender {
//...
}
Now's the consumer class:
public class MyConsumer {
readonly ISender _sender;
public MyConsumer(ISender sender){
_sender = sender;
}
//do whatever with what ISender provides
}
So here when resolving for MyConsumer, autofac should know about which version it is to pick for me, such as via some context info provider like this:
public class ContextInfoProvider : IContextInfoProvider //just an example
{
public string GetCurrentVersion(){
//can return some value picked from HttpContext.Current.Request
//or any ambient variable that can be injected at some very early time.
}
}
That's kind of a service (very fast service) to help autofac know of which should be taken into account (as an input, a parameter) for the instance resolving process.
I know this is possible but may have not been implemented yet by autofac. It's really a pity. Do you have any alternative solution with the current features supported by autofac? Please note that I don't want to use service-locator-like code, sometimes we have to use it that way but almost the time we need a constructor-dependency-injection's way, it's just neat and clean.
You could register a lambda. Put the factory logic in that lambda.
builder.Register(ctx =>
var version = ctx.Resolve<IContextInfoProvider>().GetVersion();
if(version == 1)
{
return new SlowSender();
}
return new FastSender();
).As<ISender>();

Injecting different implementations of an interface into different controllers with Autofac

I have a IFileSystemService interface, which defines a set of file & directory management functions. It has an implementation and is injected by Autofac into controllers that need it.
However, for reasons out of our control, we now have a requirement to move one specific part of the website to use database instead of the filesystem, while maintaining the same functionality (i.e., a "lite" version of a filesystem using database for storage). For this, I have created a second implementation of IFileSystemService, which works with the DB instead of the actual filesystem.
However, I can't figure out how to tell Autofac to use this second implementation on the specific controller(s) that need it, while leaving the original implementation as the default for all others.
Services can be "named" in AutoFac as per https://code.google.com/p/autofac/wiki/TypedNamedAndKeyedServices
To register the Db implementation of the IFileSystemService as a named instance:
builder.Register<MyDbFileSystemService>().Named<IFileSystemService>("DbFileSystemService");
Then to get the dependent controller to use the named registration:
builder.Register(c => new MyControllerWithDbDependency(c.Resolve< IFileSystemService >("DbFileSystemService")))
.As<Controller>()
.etc
In the case of the updated question when this is not feasible due to the large number of additional dependencies, I would do one of the following:
Move the IFileSystemService dependency into a property of the controller
Abstract the resolution of the IFileSystemService into a factory and dynamically resolve the dependency at runtime
Register the concrete IFileSystemService implementations as services for their own specific types and then use specific implementations within the signature of the controller constructor
IFileSystemService Factory
public class MyControllerWithDbDependency : Controller
{
MyControllerWithDbDependency(IFileSystemServiceFactory fileSystemServiceFactory,
ISomeOtherDependency ...)
{
_service = fileSystemServiceFactory.Create("MyDbFileSystemServiceFactory");
}
}
public interface IFileSystemServiceFactory
{
IFileSystemServiceFactory Create(string dependencyName);
}
public class AutoFacFileSystemServiceFactory : IFileSystemService
{
private readonly IComponentContext _componentContext;
public AutoFacFileSystemServiceFactory(IComponentContext componentContext)
{
if (componentContext == null) throw new ArgumentNullException("componentContext");
_componentContext = componentContext;
}
public IFileSystemService Create(string dependencyName)
{
return _componentContext.ResolveNamed<IFileSystemService>(dependencyName);
}
}
I.e. each controller is responsible for specifying the specific IFileSystemService dependency it requires, which in turn means no alteration to the AutoFac configuration for the controllers.
To be honest, I usually only use this technique in situations where the specific type to be resolved is genuinely not known until runtime - unlike in the case of the question where it would be used as a workaround.
Obviously if you have a large number of controllers and a small set of IFileSystemService implementations, and if it makes sense from a design perspective, you could push the call to Create on the factory to a custom controller base type and save yourself some code duplication.
Register specific implementations of IFileSystemService as services of themselves
public class MyControllerWithDbDependency : Controller
{
MyControllerWithDbDependency(MyDbFileSystemService dbFileSystemService,
ISomeOtherDependency ...)
{
// ...
}
}
// AutoFac configuration
builder.RegisterType<MyDbFileSystemService>()
.As<MyDbFileSystemService>()
.InstancePerWhatever();
builder.RegisterType<DefaultFileSystemService>()
.As<IFileSystemService>()
.InstancePerWhatever();

Generic Vs Dependency injection

Is there any difference between Generic Classes and Dependency injection ? Are they not ways to implement Inversion of Control
Is generic class not a way to implement Dependency Injection with added benefits of compile time safety ?
For Example, if I have a node class, then I can define as following
class Node<T> where T : ISomeInterface
{
..
..
}
class Node
{
ISomeInterface obj
public Node(ISomeInterface inject)
{
obj = inject;
}
}
UPDATE 2
With New
class Node<T> where T : ISomeInterface, new()
{
ISomeInterface obj
public Node()
{
obj = new T();
}
}
Update 3
#akim : I have made the example that you asked for using Generics
Repository using Generics
Interface IRepository
{
public DataTable GetAll();
}
public class ProductRep : IRepository
{
public DataTable GetAll()
{
//implementation
}
}
public class MockProductRep : IRepository
{
public DataTable GetAll()
{
//mock implementation
}
}
public class Product<T> where T : IRepository, new()
{
IRepository repository = null
public Product()
{
repository = new T();
}
public List<Product> GetProduct()
{
DataTable prodlst = repository.GetAll();
//convert to List of products now
}
}
//so while using the Product class, client would Supply ProductRep class and in NUnit you //would supply MockProductRep class
Product<ProductRep> obj = new ProductRep<ProductRep>();
List<Product> lst = obj.GetProduct();
//in NUnit
Product<MockProductRep> obj = new ProductRep<MockProductRep>();
List<Product> lst = obj.GetProduct();
They are not the same. Generic types allow you to define functionality that can be applied to a wide range of other types. However when you instantiate a generic class, the compiler makes a reference to the actual types that were passed as generic parameters. So the declaration is static and cannot change after compilation. For example, I can write code that instantiates your Node class:
Node<SomeImplementation> node1 = new Node<SomeImplementation>();
Node<SomeOtherImplementation> node2 = new Node<SomeOtherImplementation>();
I am reusing your Node class in different scenarios, but once I have compiled my assembly, I cannot change the generic type of my variables (node1 and node2).
Dependency Injection (and IoC containers), on the other hand, allow you to change the functionality of your app at runtime. You can use Dependency Injection to swap out one implementation of ISomeInterface with a totally different implementation at runtime. For example, in your second node class, I can use an IoC container to create the Node class... something like:
Node n = Container.Create<Node>();
The IoC container then figures out how to instantiate the Node class based on some configuration. It determines that the constructor needs an implementation of ISomeInterface, and it knows how to build an implementation at runtime. I can change my configuration for the IoC container and execute the same assembly/code and a different implementation of ISomeInterface will be created and passed to the constructor of Node.
This is useful in unit tests, because you can mock out certain parts of your application so that one specific class can be tested. For example, you may want to test some business logic that usually accesses a database. In your unit test, you can mock your data access logic and inject new functionality that returns 'static' data that is needed to test each particular business case. This breaks your tests dependency on the database and allows for more accurate/maintainable testing.
Edit
With regards to your update, the parameter-less constructor restriction may not always be desired. You may have a class (written by you or a third party) that requires parameters. Requiring a class to implement a parameter-less constructor may effect the integrity of the application. The idea behind the DI pattern is that your Node class doesn't need to know how the class was actually created.
Suppose you had many layers of classes/dependencies. With generic types, it might look like this:
class MyClass<T>
where T : IUtilityClass
{
...
}
class UtilityClass<T> : IUtilityClass
where T : IAnotherUtilityClass
{
...
}
class AnotherUtilityClass : IAnotherUtilityClass
{
...
}
In this case, MyClass uses UtilityClass, and UtilityClass depends on AnotherUtilityClass. So when you declare MyClass, you must know every dependency down the line... not just the dependencies of MyClass, but also the dependencies of UtilityClass. This declaration looks something like this:
MyClass<UtilityClass<AnotherUtilityClass>> myTestClass =
new MyClass<UtilityClass<AnotherUtilityClass>>();
This would get cumbersome as you add more and more dependencies. With DI, your caller doesn't need to know about any of the nested dependencies because the IoC container automatically figures them out. You just do something like this:
MyClass myTestClass = Container.Create<MyClass>();
There's no need to know anything about the details of MyClass or it's utility classes.
There are usually other benefits to IoC containers as well, for example many of them provide forms of Aspect Oriented Programming. They also allow you to specify the lifetime of an object, so an object could be a singleton (only one instance will be created, and the same instance will be returned to all callers).
Generics introduce the concept of type parameters, which make it possible to design classes and methods that defer the specification of one or more types until the class or method is declared and instantiated by code msdn. And generics with all their restrictions and check are applied during compile time using static analysis.
In other hand, Dependency injection is a software design pattern that allows a choice of component to be made at run-time rather than compile time wiki. And object coupling is bound at run time by an assembler object and is typically not known at compile time using static analysis wiki.
Answer on your question: one applied at compile time using static analysis, another applied at run time using XML or in-code configuration (it should be also valid for compile). Using Dependency injection decision about binding will be postponed until more information or configuration will be available from the context. So generics and dependency injection are different, and used for different purpose.
Sample #3 answer
Let's move one step further and provide Repository<Entity> to Controller and think about it usage. How are you going to implement controler's constructor:
public ControlFreakController<Repository<Entity>>()
{
this.repository = new Repository<Entity>(); // here is a logical problem
}
or
public ControllerWithInjection(IRepository repository)
{
this.repository = repository;
}
And how will you cover ControlFreakController with tests, if it depends on Repository<Entity> (literally hardcoded)? What if Repository<Entity> has no default constructor, and has its own dependencies and life time (for example, there should be one and only one repository rep HTTP request)? What if next day it will be required to audit work with Repository<Entity>?
I'm going to assume you mean your generic class to look like this:
class Node<T> where T : ISomeInterface {
T obj;
public Node(T inject) {
obj = inject;
}
}
..in which case, you're just opening up a generic type for dependency injection (with a restraint). You haven't discovered a different "method" of dependency injection - it is still dependency injection.
This wouldn't be very useful in a "real-world" scenario. You've made assumptions on how the type parameter would be used purely based on injecting it and restraining it. Also, you'll only ever be able to inject 1 single type of object into this, which is a very bad assumption.
After your update using new(), you've got even more issues. Your injected type must allow parameterless construction. That limits you even further.

Is this basically what an IOC like NInject does?

Normally I would do this:
public class DBFactory
{
public UserDAO GetUserDao()
{
return new UserDao();
}
}
Where UserDao being the concrete implementation of IUserDao.
So now my code will be littered with:
DBFactory factory = new DBFactory();
IUserDao userDao = factory.GetUserDao();
User user = userDao.GetById(1);
Now if I wanted to swap implementaitons, I would have to go to my DBFactory and change my code to call a different implementation.
Now if I used NINject, I would bind the specific implementation on application startup, or via a config file. (or bind based on specific parameters etc. etc.).
Is that all there is too it? Or is there more?
(reason I am asking if I want to know how it will help me here: Help designing a order manager class)
In a word, yes. Your code would then change in structure, so your dependencies would be passed in via the constructor (or setters, which I am personally not a fan of). You would no longer say "new XXX()" for services in the body of your methods.
You also would not likely need the factory anymore at all, since the DI framework can act as a factory. You would likely just need a constructor dependency on IUserDAO.
So something like:
public class ClassThatNeedsUserDAO
{
private readonly IUserDAO _userDAO;
public ClassThatNeedsUserDAO(IUserDAO userDAO)
{
_userDAO = userDAO;
}
public User MyMethod(userId)
{
return _userDAO.GetById(int userId);
}
}
There is more to it, one example would be if the constructor of UserDao required some other objects to be passed as arguments (dependencies).
You could have ninject automatically create and inject those objects, saving some lines of code but more importantly ensuring that every class is loosely coupled with its dependencies.

Categories