Hope this makes sense:
I have two classes:
ZombieRequest
VampireRequest
They both have to dependency inject:
ICreatureRequest
(which holds endpoints that ZombieRequest and VampireRequest must use)
They both derive from abstract class:
MonsterRequest
(which includes a common method for both ZombieRequest & VampireRequest (validates the response sent back from ICreatureRequest). Also defines how it should be used as an API (success variable, error variable, and a sendRequest() method))
Here's like the pseudo code of how it looks:
ZombieRequest : MonsterRequest
~~ use ICreatureRequest API endpoint~~
~~ use MonsterRequest method to validate the response~~
VampireRequest: MonsterRequest
~~ use ICreatureRequest API endpoint~~
~~ use MonsterRequest method to validate the response~~
In my controller I want to use ZombieRequest and/or VampireRequest, but I am getting lost with how to actually get it in there and use it.
Do I make an IMonsterRequest and inject that in the controller's constructor? But then how do I use a ZombieRequest or a VampireRequest from that?
Controller:
Get(string someVariable, string anotherVariable)
{
ZombieRequest z = new ZombieRequest();
if (z.SendRequest(someVariable, anotherVariable).Success)
string zombieData = z.ResponseData
}
ZombieRequest:
class ZombieRequest : MonsterRequest
{
ICreatureRequest m_CreatureRequest;
public ZombieRequest(ICreatureRequest c)
{
m_CreatureRequest = c;
}
public MakeRequest(someVar, anotherVar)
{
var response = m_CreatureRequest.GetZombie(someVar, anotherVar);
ValidateAndSetResponseData(response);
}
}
MonsterRequest:
abstract class MonsterRequest
{
public bool Success;
public string Data;
public abstract MakeRequest(someVar, anotherVar);
public void ValidateAndSetResponseData(var response)
{
// read response and:
// set Success
// set Data
}
}
But apparently I still need to supply a 'ICreatureRequest' when I make the object. Little confused.
Okay, this is starting to make sense so I'll take a crack at an answer. You need to learn the difference between Dependency Injection and a Dependency Injection Framework (sometimes called an Inversion of Control Container or IoC Container).
Your VampireRequest and ZombieRequest classes are set up to allow dependency injection. Your constructors accept the dependencies needed by the code. Your Controller, however, is clearly not set up for dependency injection since you are newing up a request.
So, focusing on the Vampire and Zombie classes..
First, I'll suggest you could move the ICreatureRequest up the hierarchy into MonsterRequest.
More importantly, in order to use dependency injection and create a VampireRequest, you have no choice but to create an instance of ICreatureRequest first. Since you are doing the newing in your controller, you will have to get an instance of the ICreatureRequest there too.
As you identified, why should the controller know about a specific instance of ICreatureRequest just to use MonsterRequest? It probably shouldn't. So you have a few choices: 1) ignore this rule and just have your controller create the ICreatureRequest. 2) inject an ICreatureRequest into the controller. 3) inject a fully created MonsterRequest into the controller. 4) Use an IoC Container to create all your dependencies for you automatically.
You've already made it clear you don't like the sounds of option 1. If you go with option 2 or 3 you'll soon notice that someone needs to new up the ICreatureRequest to pass to the Controller, so you'll probably be back in a few hours. Option 4 is probably the gap in your understanding and pretty much what everyone is talking about when they say dependency injection. It's also a much larger topic than I want to broach here, so instead I'll just refer you to documentation for one of my personal favourites: https://simpleinjector.readthedocs.io/en/latest/index.html
Related
Preface - we have an old service that we need to upkeep and occasionally modify. Its architecture is not good, and it is a mammoth, but since we hope to deprecate it eventually my company does not want to currently fix its architecture.
Question:
I have a class MS. I need to change one of its methods so that instead of calling HTTP directly, it will do so via another existing class, AEO. AEO inherits from abstract class EC, has several fields it receives by means of DI, and is set up to be received by DI as well.
MS is not created via DI. Rather, the program.cs file that calls the method that adds DI, it creates a new instance of MS, manually passing its necessary parameters in.
How can I access AEO from within MS? If I just create new AEO(...) I will have an issue with passing the DI parameters which I do not have. If I just declare the Interface/Indexer as I would with normal DI, then upon creating new MS(...) I will have an issue of lacking the parameter to pass in to the constructor.
How can I make this work? Is it possible?
TIA
EDIT:
The way that AEO is declared with DI is thus:
builder.RegisterType<AEO>().Keyed<EC>(MCType.AEO)
.SingleInstance().WithAttributeFiltering();
answer edited 15-Dec-2022
Whenever I've had to perform this kind of refactoring in the past I've approached it from a different angle.
In order to mitigate risk the first step is to introduce your old service to the dependency injection process.
This will allow you to introduce replacement services, again using DI as you replace functionality.
Thus, you create an interface, IMS from MS, register that with your DI Container and then change your calling code to no longer work with a concrete instance of MS but IMS allowing the DI container to do its work.
Let us assume, for arguments sake that IMS is defined as:
interface IMS
{
public FunctionOne();
public HTTPFunction();
}
so that MS now implements that interface e.g.,
class MS : IMS
{
public FunctionOne()
{
//Do some work
}
public HTTPFunction()
{
//Make some HTTP calls
}
}
So you register MS interface (IMS) with DI container something like:
Container.Register<IMS, MS>("OldMS");
Thus you change in program.cs from
var msInstance = new MS();
to
var msInstance = Container.Resolve<IMS>("OldMS");
Testing should show that the program behaviour has not changed.
Next you wish to introduce AEO functionality for the one call in MS.
AEO inherits from abstract class EC, has several fields it receives by means of DI, and is set up to be received by DI as well.
You fail to mention whether AEO implements any additional methods or properties to those that it inherits from EC so I'll assume that it's registered with an interface IAEO e.g.,
Container.Register<IAEO, AEO>();
If not then please interpolate where necessary.
Next we create a wrapper class around MS functionality that implements the IMS interface e.g.,
class MSTwo : IMS
{
private IMS oldMs;
private IAEO aeo;
public MSTwo()
{
oldMS = Container.Resolve<IMS>("OldMS");
aeo = Container.Resolve<IAEO>();
}
public FunctionOne()
{
oldMS.FunctionOne();
}
public HTTPFunction()
{
aeo.SomeFunction();
}
}
This class you register with your DI Container e.g.,
Container.Register<IMS, MSTwo>("NewMS");
and it can then be resolved within program.cs
var msInstance = Container.Resolve<IMS>("NewMS");
Note: In the above examples, for simplicity, I've omitted any reference to DI through constructors, their registration with the DI Container nor there resolution at runtime as the syntax is often DI Container dependent.
Thanks to #Oliver Jacot-Descombes` comment, I found a working solution.
Before calling new MS(...) I used reflection to get an instance of AEO.
aeo = container.ResolveKeyed<EC>(MCType.AEO) as AEO;
and then passed aeo in to the new MS(...,aeo)
Im looking to this example to understand the use of factory pattern.
I'm really amator in this field so excuse my silly question.
My problem is that i don't see the use of the factory pattern which return us the interface that we can inject it directly when we need to use it.
In the example above I would do something like this:
public class Program
{
// register the interfaces with DI container in a separate config class (Unity in this case)
private readonly IShippingStrategy _shippingStrategy;
public Program(IShippingStrategy shippingStrategy)
{
_shippingStrategy= shippingStrategy;
}
public int DoTheWork(Order order)
{
// assign properties just as an example
order.ShippingMethod = "Fedex";
order.OrderTotal = 90;
order.OrderWeight = 12;
order.OrderZipCode = 98109;
int shippingCost = _shippingStrategy.CalculateShippingCost(order);
return shippingCost;
}
}
Instead of injecting the factory :
public class Program
{
// register the interfaces with DI container in a separate config class (Unity in this case)
private readonly IShippingStrategyFactory _shippingStrategyFactory;
public Program(IShippingStrategyFactory shippingStrategyFactory)
{
_shippingStrategyFactory = shippingStrategyFactory;
}
public int DoTheWork(Order order)
{
// assign properties just as an example
order.ShippingMethod = "Fedex";
order.OrderTotal = 90;
order.OrderWeight = 12;
order.OrderZipCode = 98109;
IShippingStrategy shippingStrategy = _shippingStrategyFactory.GetShippingStrategy(order);
int shippingCost = shippingStrategy.CalculateShippingCost(order);
return shippingCost;
}
}
Why taking the bruden to create a factory (thus adding an extra layer) when we can inject the interface directly to wherever we need to use it ?
I think you don't want just another article about the factory pattern but a short comprehensive answer.
So, I'd like to focus on two things.
More flexibility
Most commonly, you'd set up your composition root where you basically say ...
"if anyone wants IAnyService, he should get MyAnyServiceImplementation".
This is fixed for your application. Once set up, your dependency injection container will serve the class instances you registered but you should not try to re-configure that container again. That's perfect for startup flexibility like registering implementation for data access components by the application's configuration, for example. Say ...
"if anyone wants IUserRepository, he should get MsSqlUserRepository because we are working with MSSQL server".
Of course, having that "immutable" composition root limits the possibilities to choose an implementation in runtime depending of the applications' state.
Instead you can inject a class which decides on a current state which service implementation to choose. Data validation is a typical scenario for that pattern because there might be different rules for different entities on your system. The buzzword here is "rule pattern" or "strategy pattern".
Lifetime control
Think of a long-living class instance like a view (user interface) or any class attached to it (like a viewmodel or a controller). As long as a user is active on a view, the class is alive. By injecting a class instance to the constructor of the view controller, for example, you hold an active instance of it as long as the view lives.
Let's say you want to use a data repository to connect to a database for example. These database access calls should be short and you do not want to keep connections open for a long time. With a repository factory, you could control the lifetime very precisely and make sure that the class is removed after it has been used:
using (var repository = new _factory.CreateRepository(...))
{
return repository.GetAnything();
}
With this, a very lightweight class - the factory - gets injected and lives as long as the view controller lives. The heavy classes - the connection things - should not live long and are just created when needed.
In fact, chances are that the repository is not instantiated at all if there's no requirement to load the data (because of an upfront cache hit, for example). If you would have injected the repository directly, you'd guarantee that one long living instance lives in memory in every case.
If you check the code for the factory you can see that depending on the ShippingMethod of the order a different implementation of the IShippingStrategy is returned by the factory. Since the ShippingMethod is only known once DoTheWork has been called it's impossible to inject the right implementation when the class is constructed (and the same class might even need different implementations for different orders).
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.
Hello, I'm trying to implement a ViewModelFactory "pattern" and I was wondering what's the best way to achieve it, considering the constraints of the current IoC container.
public class UserCreateViewModelFactory
{
private readonly DbContext db;
public UserCreateViewModelFactory(DbContext db){ this.db = db;}
public void Create(CreateUserViewModel viewModel)
{
//Creates the user
}
}
I have the above class easily injected into my controllers ctor. The head ache will come when I need more ViewModelBuilders, So I want to avoid two things:
Bloat ctor with injections
Bloat container with registrations
I want to be able to inject an IViewModelFactory on my controller and then using it like this:
[HttpGet]
public IActionResult GetUsers(int id)
{
return View(viewModelFactory.Build<GetUserViewModel>(id));
}
Notice that on calling Build(T) it has to call the correct IViewModelFactory implementation.
I know that StructureMap container support binding the concrete implementations to the corresponding interface but I'm trying to come up with a solution without having to add another dependecy to the project.
I think if you have builders for building viewmodels, then factory is extra layer of abstraction which simply can be dropped off.
Because you know the type of created viewmodel at compile time you can just inject a builder you need to the controller constructor.
If your controller create a lot of viewmodels and you end up with a lot of builders you need to inject - this can be considered as a sign of violation of Single Responsibility Principle. In that case you need to separate logic of controller to different controllers.
So I want to avoid two things:
Bloat ctor with injections
Separate class with bloated constructor to another classes with more specific responsibility which takes smaller amount of dependencies.
Or wrap dependencies with one or two, three classes based on their relation
Bloat container with registrations
This cannot be a problem, because dependency containers is usually designed to register whole "object graph" of your application
After sometime researching, I finally came up with a good solution for the this problem.
The solution is basically extending the default IoC capabilities through an IServiceCollection.ConnectImplementations() extension method.
During registration I'll search my concrete classes and connect them with its respective interfaces (like other containers). Then I use a Mediator/Proxy that has IServiceCollection injected and knows which concrete class should be building the view model.
The full solution is better explained by this gist I've created.
What is best way to get injections in base controller when using C# StructureMap.Mvc?
I can think of these 2 ways and don't know which is better.
From controller arguments to base controller arguments
(Nice approach but becomes a mess when there are many controllers with many properties to be injected)
Don't use child controller and initiate all injections using ObjectFactory.CreateInstance() in base controller constructor
(Very less code and manageable but not considered as good practice when Controller Injection is available)
thanks in advance.
I think bother approaches are fine and you can use the mix of both. Of course depending in the situation.
A. I believe if your child Controller require a dependency to be injected, then use the Constructor injection. This way you Controller's constructor API is explicit and it should state what has been injected into the Controller. Easy to read, and easy for discoverability. If you try to hide your DI types in a factory you lose this nice API/discoverability. Use property injection when the dependencies are optional if you think so. You don't really have pass these to the base Controller unless all your Child Controllers use them.
If you think you overloading the types in your Controller, try to aggreagate those interfaces to a single types.
B. It is not advisable to directly use the Structure map ObjectFactory in your Controller. Your Controllers should be agnostics of any infrastructure DI work. You can make use a generic factory (in infrastructure) to create types which uses the ObjectFactory within. If your DI types are required by the base Controller you may use this factory to resolve those types.
The ideas, inject types only when/where they need. Avoid injecting types to Controllers when they don't use/need.
Another option you available to you is setter injection via StructureMap's ObjectFactory.BuildUp() method.
It's worth mentioning that in StructureMap 3.1 the ObjectFactory has been deprecated in favour of injecting an instance of IContainer.
The examples would look like this:
StructureMap 3.0 and below:
public class BaseController {
protected IMyExampleServer MyExampleService { get; set; };
public BaseController() {
ObjectFactory.BuildUp(this);
}
....
}
StructureMap 3.1+:
public class BaseController {
protected IMyExampleServer MyExampleService { get; set; };
public BaseController(IContainer container) {
container.ObjectFactory.BuildUp(this);
}
....
}
Using StructureMap 3.1 would mean you'd only need to inject an instance of IContainer into your derived controller rather than each individual dependency that your base class requires.