I just started using the Unity Application Block to decouple my classes and make unit testing easier. However, I've run into a problem with circular dependencies.
I have a facade-type class which is a chat bot. It is a singleton class which handles all sort of secondary classes and provides a central place to launch and configure the bot. I also have a class called AccessManager which, well, manages access to bot commands and resources. Boiled down to the essence, I have the classes set up like so:
public class Bot
{
public string Owner { get; private set; }
public string WorkingDirectory { get; private set; }
private IAccessManager AccessManager;
private Bot()
{
// do some setup
// LoadConfig sets the Owner & WorkingDirectory variables
LoadConfig();
// init the access mmanager
AccessManager = new MyAccessManager(this);
}
public static Bot Instance()
{
// singleton code
}
...
}
And the AccessManager class:
public class MyAccessManager : IAccessManager
{
private Bot botReference;
public MyAccesManager(Bot botReference)
{
this.botReference = botReference;
SetOwnerAccess(botReference.Owner);
}
private void LoadConfig()
{
string configPath = Path.Combine(
botReference.WorkingDirectory,
"access.config");
// do stuff to read from config file
}
...
}
I would like to change this design to use the Unity Application Block. I'd like to use Unity to generate the Bot singleton and to load the AccessManager interface in some sort of bootstrapping method that runs before anything else does.
public static void BootStrapSystem()
{
IUnityContainer container = new UnityContainer();
// create new bot instance
Bot newBot = Bot.Instance();
// register bot instance
container.RegisterInstance<Bot>(newBot);
// register access manager
container.RegisterType<IAccessManager,MyAccessManager>(newBot);
}
And when I want to get a reference to the Access Manager inside the Bot constructor I can just do:
IAcessManager accessManager = container.Resolve<IAccessManager>();
And elsewhere in the system to get a reference to the Bot singleton:
// do this
Bot botInstance = container.Resolve<Bot>();
// instead of this
Bot botInstance = Bot.Instance();
The problem is the method BootStrapSystem() is going to blow up. When I create a bot instance it's going to try to resolve IAccessManager but won't be able to because I haven't registered the types yet (that's the next line). But I can't move the registration in front of the Bot creation because as part of the registration I need to pass the Bot as a parameter! Circular dependencies!! Gah!!!
This indicates to me I have a flaw in the way I have this structured. But how do I fix it? Help!!
You can make your life easier by changing the design in the following ways:
Don't implement the Singleton pattern yourself. The DI Container should manage the lifetime of all components, including the Bot class. If you only want a single instance in your application, configure Unity to always return the same instance.
Do everything in your power to remove circular dependencies. You can often do that by changing one of the communication directions to use events instead of direct calls. Another option is to introduce a Mediator.
Notice that none of these recommendations particularly involve Unity. Unity (or any other DI Container) is not a silver bullet that will magically make your code loosely coupled. You must first understand the principles behind DI, and then you can use any DI Container as a tool to help you wire up the dependency graph.
First of all you should let the container manage your singleton lifetime instead of writing the singleton code yourself. To remove your circular dependency, you can remove the Bot from the access manager constructor. Instead, you use an initialize method.
container.RegisterType<Bot>(new ContainerControlledLifecycleManager()); // from my memory...
container.RegisterType<IAccessManager,MyAccessManager>();
var bot = container.Resolve<Bot>();
// Bot.cs
public Bot(IAccessManager manager)
{
manager.InitializeFor(this);
}
For testability reasons you should never call your IOC container from a constructor.
Related
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
I am struggling to determine if this is the correct method for injecting dependencies from my Console Application Main method into my primary application class instance.
I have the following code:
Program Class
static void Main(string[] args)
{
var container = new SimpleInjector.Container();
// Registrations here.
container.Register<ILogger, FileLogger>();
//Verify the container.
container.Verify();
ILogger log = container.GetInstance<ILogger>();
log.Info("Logging From Main Method");
//Start Main Agent
MainAgent agent = new MainAgent(log);
agent.Start();
}
Main Agent Class
public class MainAgent
{
private ILogger log;
public MainAgent(ILogger _log)
{
log = _log;
}
public void Start()
{
//Main Application Code here.
Console.WriteLine("main Agent Started.");
log.Info("Logging through logger in MainAgent Class");
Console.ReadLine();
}
}
I come from a background of writing DotNetCore applications in ASP.Net Core, so I am used to how the DI works with that, registering a service into the pipeline, and them all being available for me to cherry pick in each controller's Constructor.
My worry is I may have 20-30 services, all of which will all need to be injected in as parameters each time I “New Up” a new instance of a class for them to be avaliable to the constructor in my new class.
Am I missing some magical feature which will just make all my registered services available in any newly initialized constructor for me to reference as I do with ASP.Net Core?
No, there is no magic.
What you are missing is that AspNetCore automatically resolves your controller under the covers, which resolves the entire object graph of dependencies that controller has (that is, any dependencies of the controller, dependencies of those dependencies, etc.)
Similarly, in a console app, you need to resolve the entire object graph (usually at startup).
static void Main(string[] args)
{
// Begin Composition Root
var container = new SimpleInjector.Container();
// Registrations here.
container.Register<ILogger, FileLogger>();
container.Register<IMainAgent, MainAgent>();
//Verify the container.
container.Verify();
// End Composition Root
MainAgent agent = container.GetInstance<IMainAgent>();
//Start Main Agent
agent.Start();
}
Effectively the "agent" is should be considered to be the entire application. The console is just a shell to set everything in motion. Do note that it would probably be sensible in most situations to pass in the args from the console app, so they can be parsed and responded to by the "agent" as appropriate.
agent.Start(args);
Am I missing some magical feature which will just make all my registered services available in any
Simple answer yes you are SimpleInjector supports direct object creation
var agent = container.GetInstance<MainAgent>();
With out the need to register the instance at all.
You can make an interface and then register like you do ILogger but making the method virtual and using directly the class name is also fine. You can read more on the subject here
I've recently been dabbling a bit with IOC Containers (LightInject in my case).
I've been reading that you should only need to use the container ONCE, on startup, and no where else. This is what I'm struggling to understand. If I can only reference the container in a bootstrap/startup method, how is it possible to resolve what I need, elswhere in the project, or at runtime if the class depends on user input.
So In my Traditional Windows Forms App, on Form Load Say, I would Bootstrap Lightinject as per the below code. It's only an arbitrary example, it's more the premise I need to get my head around.
I might be missing something here entirely, or just not getting it. But how am i supposed to resolve dependancies, If i can't use/not supposed to reference or use Container.GetInstance/Resolve/{Choose IOC Syntax Here}, and only in the composition root.
For Instance, Say I have two buttons and a TextBox on my form. The first button gets me an ILoader (below code), and the second button loads up a file viewer (ILoader, below code), whose file name is what is entered into the textbox on the winform.
Without An IOC Container I would do the following (let's just assume its put in the click event)
Button 1 Click Event :
ISplitText MyStringFunc = new WhateverImplementsIt();
Button 2 (gets the file reader based on textbox input)
ILoader MyLoader = new FileReaderImplementation(TextBox1.Text);
Using LightInject, I'm surely compelled to do the following:
Button1 Click:
ISplitText Splitter = Container.GetInstance<ISplitText>();
Button 2 Click
var LoaderFunc = Container.GetInstance<Func<string, ILoader>>();
ILoader l2 = LoaderFunc(TextBox1.Text);
Am I Incorrect? In A large project I would have Container.GetInstance, peppered all over the place, in the main form file and elsewhere surely, so how can i only reference the container in ONLY 1 spot, in the form of bootstrap, am i missing a magic piece of the puzzle?
In all the sample apps I have seen it's all done in one simple console app, in the Main function. All these apps follow the format of:
Container = new Container();
Container.Register<IFoo,Foo>();
Container.Register<IBar,Bar();
var Resolved = Container.GetInstance<IFoo>();
Well, I understand all that, and it's extremely simple. It's once you start adding a bit of complexity to the app itself, I'm lost as to how to get the instances without making the Container itself public, or static, or accessible in some way,shape or form and then calling Container.GetInstance in a million places (which apparently, is a big no no). PLEASE HELP!
Cheers,
Chud
PS - I am not concerned about "abstracting the container" itself. so would prefer to only focus on increasing my understanding of the above.
public class BootStrapIOC
{
public ServiceContainer Container;
public BootStrapIOC(ServiceContainer container)
{
Container = container;
}
public void Start()
{
Container.Register<ISplitText, StringUtil>();
Container.Register<string, ILoader>((factory, value) => new FileViewByFileName(value));
}
}
//HUH? How can i NOT use the container??, in this case in the button_click
ILoader Loader = Container.GetInstance<Func<string, ILoader>>();
ILoader l2 = Loader(TextBox1.Text);
ISplitText Splitter = Container.GetInstance<ISplitText>();
EDIT #1
OK, so, after re-reading the comments and looking at a few more examples on the interweb, I think I may finally understand it. The issue was (I think) is that i wasn't thinking "higher level" enough. I was trying to resolve my dependancies in my winforms application, AFTER the form had already been constructed,and in the form itself. When in reality, it's too late by then. I wasn't viewing the "form itself" as just another object, which needed it's dependencies injected into it.
So I bootstrap now in my Program.cs:
static class Program
{
private static ServiceContainer Container;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Container = new ServiceContainer();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
BootStrapIOC Strap = new BootStrapIOC(Container);
Strap.Start();
//This magic line resolves EVERYTHING for me required by the Form
var form = Container.GetInstance<Form1>();
Application.Run(form);
//Application.Run(new Form1());
}
}
My question now is, Is my line of thinking now correct in terms of winforms. It seems to make more sense, changing my approach to "higher up" the chain and resolving from Program.cs??
Secondly, And I'm not sure if this calls for a new question altogether, please advise as I am an SO noob.
How would I setup a factory to return the correct instance of an object? One of the original comments indicated that that would be a usage in this scenario. Let's use a contrived example.
Where I needed an object, but don't know which object until run time/user input.
My Idea:
BootStrap
Container.Register();
Factory Interface and Implementation:
Let's put some optional parameters in also, as I want to know if this is the correct/best way to do it?
public interface IFileViewerFactory
{
ILoader GetFileViewer(string FileName, string Directory = null, bool CreatingDirectory = false);
}
public class FileViewerFactory:IFileViewerFactory
{
public FileViewerFactory() { }
public ILoader GetFileViewer(string FileName, string Directory = null, bool CreatingDirectory = false)
{
if (CreatingDirectory == false)
{
if (Directory == null)
return new FileViewByFileName(FileName);
else
return new FileViewByDirectoryName(Directory, FileName);
}
else
return new FileViewByDirectoryNameCreateDirectoryOptional(Directory, FileName, CreatingDirectory);
}
}
Form:
public IFileViewerFactory FileViewerFactory { get; set; }
Button Click:
ILoader FileLoader = FileViewerFactory.GetFileViewer(TxtBoxFileName.Text);
Or:
ILoader FileLoader = FileViewerFacotry.GetFileViewer(TxtBoxFileName.Text,TxtBoxDirectory.Text);
So to finish off, my questions are:
Is my new way of "higher level" thinking, and bootstrapping from Program.cs now correct
How Can I handle optional parameters in LightInject
Is How I have setup my factory the correct way to do it?
Let's forget about the Fugliness of the factory and just try to work on the mechanics of the questions :)
I know it's a bit late to answer a question that is over a year old but let me try.
The issue here is that you don't want your container to go out anywhere else than your Composition Root. In a complex solution consisting of mutliple assembiles, this means the container itself is only referenced by the topmost assembly (where the Composition Root is).
But the application stack is usually complex, you possibly have multiple assembiles and still, your depencencies should be resolves across the application.
Historically, one of the possible approaches was the Service Locator pattern. The locator goes down to the very bottom of the stack and from there, it offers a service that resolves dependencies. Thus, it's available anywhere up the stack.
This approach has two drawbacks, first is that your container is referenced at the very bottom of the stack and even if you circuvment this you still have your locator referenced everywhere. The latter could be painful in a large app as you possibly have some standalone assembiles that you don't want to be forced to reference your locator (or anything else).
The ultimate solution is called the Local Factory (aka Dependency Resolver) and it takes care of creating just few of its dependand services. The trick is then to have multiple local factories across your app.
A typical setup is like this. Suppose there's an assembly, call it A, that the client will use to obtain an instance of IServiceA. The assembly contains only the two:
interface (obligation) of the service - IServiceA
the local factory clients will use to obtain instances of the service
And that's all, no other references, no containers. There's even no implementation at this point yet. The trick here is to make the factory open for the actual provider - in a sense that the factory doesn't even yet know how to create instances - it's the Composition Root that will tell it.
// Assembly A
public interface IServiceA
{
...
}
public class ServiceAFactory
{
private static Func<IServiceA> _provider;
public static void SetProvider( Func<IServiceA> provider )
{
_provider = provider;
}
public IServiceA Create()
{
return _provider();
}
}
the provider here has a functional contract but it could also be expressed as an interface
And that's all, although there's no implementation in the factory at the moment, the client code is suddenly very stable:
// client code to obtain IServiceA
var serviceA = new ServiceAFactory().Create();
Note again how self-contained this assembly A is. It has no other references, still, it offers a clean way to obtain instances of your service. Other assemblies can reference this assembly with no other additional references.
Then comes the Composition Root.
At the very top of your stack, your main assembly references the assembly A and some other assembly, let's call it AImpl that contains a possible implementation of the service interface.
technically the implementation of the service could be in the very same assembly the interface is but it only makes things easier
The Composition Root creates the provider of the factory by delegating a factory method down the stack, to the assembly A
// Composition Root in the top level module
// Both assemblies
// * A that contains IServiceA
// * AImpl that contains an implementation, ServiceAImpl
// are referenced here
public void CompositionRoot()
{
ServiceAFactory.SetProvider( () =>
{
return new ServiceAImpl();
} );
}
From now on, the provider is set up and all the client code down the stack that uses the factory, can succesfully obtain instances.
The Composition Root provides all other implementations of other local factories, as well. There are multiple setups then in the Composition Root:
SomeLocalFactoryFromAssemblyA.SetProvider( ... );
AnotherLocalFactoryFromAssemblyB.SetProvider( .... );
...
Where is your container then?
Well, the container is just one possible implementation of the provider. It only helps rather than spoils. Note however that you don't even have to use it, it's a choice rather than obligation.
public void CompositionRoot()
{
var container = new MyFavouriteContainer();
container.Register<IServiceA, ServiceAImpl>(); // create my registrations
ServiceAFactory.SetProvider( () =>
{
// this advanced provider uses the container
// this means the implementation, the ServiceAImpl,
// can have possible further dependencies that will be
// resolved by the container
container.Resolve<IServiceA>();
} );
}
This is the most clean setup I am aware of. It has all desired features:
it separates concerns in a clean way
the client doesn't really need any other dependencies than the service contract and the factory
the client doesn't even know there is or will be a container, in fact the client doesn't care
in a test environment, providers can easily be setup without any container, to provide static mocks of your services
the Composition Root is a real composer here - it's the only place in your code where the three: interfaces, implementations and the container, meet together
Looking at this answer on SO, I am a bit confused by the following "principle":
Apply the Hollywood Principle
The Hollywood Principle in DI terms says: Don't call the DI Container, it'll call you.
Never directly ask for a dependency by calling a container from within
your code. Ask for it implicitly by using Constructor Injection.
But what if I have a repository class in my DAL, and I want to supply this instance to an object which is created when a TCP/IP client connects? At what place should I make the injection?
Right now, I have something like:
// gets created when a new TCP/IP client is connected
class Worker
{
private readonly IClient client;
public Worker(IClient client)
{
// get the repository
var repo = IoC.GetInstance<IClientMessagesRepo>();
// create an object which will parse messages
var parser = new MessageParser(client);
// create an object which will save them to repo
var logger = new MessageLogger(parser, repo);
}
}
I obviously cannot create this instance when my app is started. So where do I inject the repo?
Thanks a lot!
You should strive to only call IoC.GetInstance() once.
Since you cannot create the Worker at startup, you should instead create a WorkerFactory and have the DI container inject the dependency into that:
public class WorkerFactory
{
private readonly IClientMessagesRepo clientMessagesRepo;
public WorkerFactory(IClientMessagesRepo clientMessagesRepo)
{
this.clientMessagesRepo = clientMessagesRepo;
}
public Worker Create(IClient client)
{
return new Worker(client, clientMessagesRepo);
}
}
Move IClientMessagesRepo to your constructor arguments:
public Worker(IClient client,IClientMessagesRepo clientMessagesRepo)
Now of course this only moves the problem a bit, to the point where the worker is created. Of course at some point calls into the IoC container are necessary. But in those cases I'd rather pass in the container in a parameter than access it from a static property. Or use some kind of factory.
Have IClientMessagesRepo in your arguments, and let the IoC fill that for you:
public Worker(IClient client, IClientMessagesRepo repo)
{
[...]
}
Obviously, your constructor should do a little more than just create a couple local variables, but you get the idea.
As I understand you have the repository in your IOC container, but not the IClient. Assuming that you have access to the IOC container at the time you create your worker class, and assuming that you are using StructureMap you can write:
IClient concreteClient = ...;
worker = container.Using<IClient>(concreteClient).GetInstance<Worker>();
That way you tell StructureMap to use a specific IClient instance, but obtain the other dependencies from the repository.
note: It is some time since I last used StructureMap, so perhaps the code is not 100% correct, but the concept is there, you can provide a concrete dependency when creating a component.
I would like to just markup a property with an attribute [DoInjection] and have unity do the injection. I don't want to have to use prop = Unity.Resolve(type). Thats a pain and messy. Does unity provide attributes to do this or do I have to build my own?
Edit: register in App.Main
ISessionFactory sf = new SessionFactory();
container.RegisterType<IRepository, CustomerRepository>(new InjectionConstructor(sf.CurrentUoW));
container.RegisterInstance<IUnitOfWork>(sf.CurrentUoW);
Using [Dependancy] on IUnitOfWork propery in ClassX other class but it's always null. Do I need to build ClassX instance using Unity to get this to work? It looks like I do have to. I don't like that.
Unity has a DependencyAttribute you can use for this:
public class MyObject
{
private SomeOtherObject _dependentObject;
[Dependency]
public SomeOtherObject DependentObject
{
get { return _dependentObject; }
set { _dependentObject = value; }
}
}
http://msdn.microsoft.com/en-us/library/ff650198.aspx
Based on your question, it sounds like you might be trying to use Unity in the wrong spot and your design sense was telling you it didn't feel right. You should only see Unity where you bootstrap your application. That's your Main method in a console app or Global.asax in a web or wcf app. The idea is to keep relying on dependencies all the way up the chain until you get to where you bootstrap and resolve just that one top level object using your IoC container. In a console app, I do this:
class Program
{
static void Main(string[] args)
{
using (var container = new UnityContainer())
{
container
.AddExtension(new ConfigureForConsole(args))
.Resolve<MyApplication>()
.Execute();
}
}
}
http://www.agileatwork.com/console-application-with-ioc/
In this case, MyApplication is my top level object (it doesn't need to be an interface here). The ConfigureForConsole is just a one-off custom container extension that has all the RegisterType lines in there. Alternatively you could initialize the container from App.Config here. The idea though is that your Main method has almost nothing in it. Another benefit of this approach is that it makes your code more portable. I find that console apps usually turn into windows services and keeping things clean here makes that transition pretty painless.