How to use Unity to inject dependencies through factory? - c#

Imagine I have something I will create through a factory:
public sealed class MyClass
: IMyClass
{
private IMyDao MyDao { get; set; }
public MyClass(IMyDaoFactory factory)
{
MyDao = factory.MyDao;
}
}
This might resolve through a service as:
public sealed class MyService
: IMyService
{
private readonly IMyClass myClass;
public MyService(IMyDaoFactory factory)
{
myClass = new MyClass(factory);
}
}
That's easy to wire up in Unity as:
var container = new UnityContainer();
container.RegisterType<IMyService, MyService>();
container.RegisterType<IMyDaoFactory, MyDaoFactory>();
container.RegisterType<IMyClass, MyClass>();
Noting the registration of MyClass, how can I set Unity up so it will automatically register and resolve through the factory? I.e. then I no longer need:
myClass = new MyClass(factory);
Only:
this.myClass = myClass; (passed through the constructor
as IMyClass and resolved by Unity)
Hope that makes sense. Thanks in advance.

Try switching the constructor of MyService to requiring a single instance of IMyClass; Unity should automatically fill in the gaps there and instantiate based on the type signatures.
public MyService(IMyClass _myClass)
{
myClass = _myClass;
}
Although I'd also change the names up, but eh.

Related

Instantiating a class

Below is my sample code. I have this class whose constructor takes an IConfigurationRoot parameter and uses it to set a private field:
public class MyClass
{
private IConfigurationRoot _configuration;
public class MyClass(IConfigurationRoot configuration)
{
// I believe this has been injected
_configuration = configuration;
}
}
Now I want to instantiate that class:
public class AnotherClass
{
private IConfigurationRoot _configuration;
private MyClass myclass;
public SomeMethod()
{
// My _configuration here gets null in the debugger
MyClass myclass = new MyClass(_configuration);
// Rest of method omitted...
}
}
How do I properly instantiated that class so that it doesn't end up being null?
Follow this process:
1.) What I have done is map a section of the AppSettings.json file to an object.
A.) Add the configuration settings to json file.
"MyConfiguration": {
"DBServer": "MyDBServer",
"DBName": "MyDatabase"
}
B.) Create a class to use strongly typed configurations.
public class MyConfiguration
{
public string DBServer { get; set;}
public string DBName { get; set;}
}
C.) Map the JSON configurations to the MyConfiguration object in the Startup class.
public class Startup
{
//Make sure you add this.
public IConfigurationRoot Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
...
var configSection = Configuration.GetSection("MyConfiguration");
services.Configure<MyConfiguration>(configSection);
//Use one of the following.
Services.AddScoped<MyClass>();
Services.AddTransient<MyClass>();
Services.AddSingleton<MyClass>();
Services.AddInstance<MyClass>();
...
}
}
See this link for an explanation of the differences between
`AddSingleton()`
`AddScopped()`
`AddInstance()`
`AddTransient()`
2.) Change MyClass to have MyConfiguration object as a parameter of the MyClass constructor.
//add this using statement and corresponding package
//"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.1"
using Microsoft.Extensions.Options;
public class MyClass
{
private MyConfiguration _configuration;
public MyClass(IOptions<MyConfiguration> configuration)
{
_configuraiton = configuraiton.Value;
}
}
3.) Add MyClass as a parameter of the AnotherClass constructor. Dependency Injection will create the MyClass or reuse it depending on the scope of the object and how you setup that up in the Startup.ConfifureServices() method.
public class AnotherClass
{
private MyClass _myclass;
public AnoherClass(MyClass myclass)
{
_myclass= myclass;
}
public SomeMethod()
{
//Use myClass here and you don't need to instantiate it.
_myclass
....
}
}
You doing a couple of things.
1 - You are re-declaring your class variable myclass as a local variable in your SomeMethod. You should use the myclass variable you already declared as a class variable. To do that, make this line
MyClass myclass = new MyClass(_configuration);
Like this
myclass = new MyClass(_configuration);
2 - You are not instantiating your IConfigurationRoot, so it is null before inject it at all. You should be able to instantiate it however you want (ConfigurationBuilder like #Sach suggested, or _configuration = ConfigurationBuilder.Build() as #Eldho suggested), but you need to instantiate it before you inject it if you dont want it to be null.
Here, it would be best if you use an IOC container like Autofac or Unity or the built-in container in ASP.NET core(if you are using core). You would need to register your IConfigurationRoot interface and its implemented class with the IOC container. After this, inject your MyClass object using the IOC container(in the constructor, or in the method, as per your best scenario). This way, you would never face a problem.

Way to dynamically get repositories without a dependency on a DI container

I have a class that returns a repository (read only) using a generic method this is to reduce the number of repository classes I need to inject into classes in my business layer. It also allows me to add and use a new repo anywhere I have this wrapper class simply by adding a repo which implements IGenericReadRepo<T> as this will be registered in unity using the line Container.RegisterType(typeof(IGenericReadRepository<>), typeof(GenericReadRepository<>), new TransientLifetimeManager());. However this has is dependent on unity being the DI container. This smells to me.
public class ReadRepositoryWrapper : IReadRepositoryWrapper
{
private IUnityContainer _unityContainer;
public ReadRepositoryWrapper(IUnityContainer container)
{
_unityContainer = container;
}
public IGenericReadRepository<T> GetReadRepository<T>() where T : class
{
return _unityContainer.Resolve<IGenericReadRepository<T>>();
}
}
Can anyone think of a way to implement the GetReadRepository<T> without a the dependency on unity while not introducing any new dependencies. Or can someone think of another way to get repositories without having bloated constructors or a dependency on my context.
You can create generic factory interfaces/classes for dynamic object creation. Many DI containers support object creation using lambda expressions.
public interface IFactory<T>
{
T Create();
}
public class Factory<T> : IFactory<T>
{
private readonly Func<T> _creator;
public Factory(Func<T> creator)
{
if(creator == null)
throw new ArgumentNullException("creator");
_creator = creator;
}
public T Create()
{
return _creator();
}
}
The generic factory interface than can be injected into the consuming classes.
public class ReadRepositoryWrapper<T> : IReadRepositoryWrapper<T> where T : class
{
private readonly IFactory<IGenericReadRepository<T>> _factory;
public ReadRepositoryWrapper(IFactory<IGenericReadRepository<T>> factory)
{
if(factory == null)
throw new ArgumentNullException("factory");
_factory = factory;
}
public IGenericReadRepository<T> GetReadRepository()
{
return _factory.Create();
}
}
Or something like that.

Dependency Injection Container - How to keep available to

When creating an application with Dependency Injection and it utilizes a framework for Dependency Injection such as Unity (or Ninject).
How do you initialize registering the interfaces to the container at the beginning all together and keep them available for the application to use throughout its running lifecycle of the application?
Do you need to pass the DI Container to each method that may utilize dependency injection, or is there some way to make the container globally accessible so that you can register them all together in the beginning and access them throughout running the application without having to continually pass them, and be able to utilize them when ever needed?
Environment: Visual Studio 2015, C#, Microsoft Unity (for DI Container)
Example Code
static void Main(string[] args)
{
// Make Unity resolve the interface, providing an instance
// of TrivialPursuit class
var diContainer = new UnityContainer();
diContainer.RegisterType<IGame, TrivialPursuit>();
var gameInstance = diContainer.Resolve<IGame>();
var xotherClass = new AnotherClass();
xotherClass.TestOtherClassOtherMethod();
}
------ Another class without context of the Dependency Injection Class ------
public void TestOtherClassOtherMethod()
{
IGame gameInstance = -- -Container is Not available to resolve from in this class ---
}
Reason: I don't want to need to pass every possible type that I may need later on to each class I load up, I will just want to use the instances when I need them. The more deeper I get into classes, later as the application becomes more complex, I won't want to pass down instances for each type up from the Main() method to each class.
A Dependency Injection (DI) container is just that. A framework for facilitating DI. You don't pass the container around in order to resolve instances of objects. You just request the type you need in your classes constructor and the DI framework will inject the appropriate dependency.
Mark Seemann has written a good book on dependency injection that I would recommend.
You register everything that'll need to be resolved with the container in the composition root. That is to say when your program starts up is when everything should be registered.
Let's say we have the following code:
public class MyClass
{
public Run()
{
var dependency = new Dependency1();
dependency.DoSomething();
}
}
public class Dependency1
{
public void DoSomething()
{
var dependency = new Dependency2();
dependeny.DoSomethingElse();
}
}
public class Dependency2
{
public void DoSomethingElse()
{
}
}
This gives us the above dependency chain: MyClass -> Dependency1 -> Dependency2.
The first thing we should do is refactor the classes to take their dependencies through their constructor and rely on interfaces rather than concretions. We can't inject dependencies unless there is a place to inject them (constructor, property, etc).
Here is the refactored code:
public interface IMyClass
{
void Run();
}
public interface IDependency1
{
void DoSomething();
}
public interface IDependency2
{
void DoSomethingElse();
}
public class MyClass : IMyClass
{
public readonly IDependency1 dep;
public MyClass(IDependency1 dep)
{
this.dep = dep;
}
public void Run()
{
this.dep.DoSomething();
}
}
public class Dependency1 : IDependency1
{
public readonly IDependency2 dep;
public MyClass(IDependency2 dep)
{
this.dep = dep;
}
public void DoSomething()
{
this.dep.DoSomethingElse();
}
}
public class Dependency2 : IDependency2
{
public void DoSomethingElse()
{
}
}
You'll notice the classes now all take their dependencies through their constructors and do not new up anything. Classes should only take in dependencies that they actually need. For example, MyClass does not NEED a Dependency2 so it doesn't ask for one. It only asks for a Dependency1 because that's all it needs. Dependency1 NEEDS Dependency2, not MyClass.
Now to wire it all up WITHOUT a container we would just new it all up in the composition root:
void Main()
{
var myClass = new MyClass(new Dependency1(new Dependency2()));
}
You can see how that could get cumbersom if we had tons of classes and depdencies. That's why we use a container. It handles all the depdency graph for us. With a container we'd rewrite it as follows:
void Main()
{
// the order of our registration does not matter.
var container = new Container();
container.Register<IDependency1>.For<Dependency1>();
container.Register<IDependency2>.For<Dependency2>();
container.Register<IMyClass>.For<MyClass>();
// then we request our first object like in the first example (MyClass);
var myClass = container.Resolve<IMyClass>();
myClass.Run();
}
In the second example the container will handle wiring up all the dependencies. So we never need to pass Depedency2 to MyClass and then to Depedency1. We only need to request it in Dependency1 and the container will wire it up for us like in the first example.
So in your example we would rewrite it like so:
static void Main(string[] args)
{
var game = new UnityContainer();
game.RegisterType<IGame, TrivialPursuit>();
game.RegisterType<IAnotherClass, AnotherClass>();
game.RegisterType<IYetAnotherClass, YetAnotherClass>();
var gameInstance = game.Resolve<IGame>();
// you'll need to perform some action on gameInstance now, like gameInstance.RunGame() or whatever.
}
public class Game : IGame
{
public Game(IAnotherClass anotherClass)
{
}
}
public class AnotherClass : IAnotherClass
{
public AnotherClass(IYetAnotherClass yetAnotherClass)
{
}
}
public class YetAnotherClass : IYetAnotherClass {}
In these cases there is no need to pass the container around. You register your dependencies with the container then request them in your classes constructors. If you wish to use the container in the class WITHOUT requesting it through the constructor then you are not doing DI you are just using the container as a singleton service locator. Something that should generally be avoided.
Container as a Service Locator
This should be generally avoided but if you want to use the container as a service locator you have two options:
1) Pass the container into your classes that need it through the constructor.
You can use the above examples for wiring your classes up for DI. But instead of requesting a dependency like IDependency in the constructor you just pass the container.
public class Game : IGame
{
public Game(IContainer container)
{
var blah = container.Resolve<IBlah>();
}
}
2) Request your container through a static class:
public static class ServiceLocator
{
private static IContainer container;
public static IContainer Container
{
get
{
if (container == null)
{
container = new Container();
}
return container;
}
}
}
Register everything as normal in your composition root using the ServiceLocator class. Then to use:
public class MyClass
{
public void DoSomething()
{
var blah = ServiceLocator.Container.Resolve<IBlah>();
}
}

Pass parameter when initialising Dependency Injection in ASP.NET core

I have a simple class which looks like this:
public class TestClass1
{
private string testString = "Should be set by DI";
public TestClass1(string testString)
{
this.testString = testString;
}
public string GetData()
{
return testString + DateTime.Now;
}
}
I want to inject it using the build-in DI in a simple ASP.NET core web app, but with the "testString" parameter set when initialising the Dependency Injection.
I've tried setting the following in startup.cs but it fails at runtime because TestClass1 doesn't have a parameterless constructor:
services.AddScoped(provider => new TestClass1("Success!"));
I suspect you just missed the cruical part of the code and your usage of the DI is just plain wrong, not the registration.
public class MyController
{
private readonly MyClass myClass;
public MyController()
{
// This doesn't work and do not involve DI at all
// It will fail because MyClass has no parameterles constructor
this.myClass = new MyClass();
}
}
The above won't work, because DI is no compiler magic that let you magically inject dependencies when calling new on the type.
public class MyController
{
private readonly MyClass myClass;
public MyController(MyClass myClass)
{
// This should work, because the IoC/DI Container creates the instance
// and pass it into the controller
this.myClass = myClass;
}
}
When you use DI/IoC you let the constructor generate and instantiate the objects, hence you never call new in your service classes. Just tell in the constructor that you need an instance of some type or it's interface.
Edit:
This used to work in previous versions (betas) of ASP.NET Core. Should still work, but limited to parameters:
public class MyController
{
public IActionResult Index([FromServices]MyClass myClass)
{
}
}

Autofac factory instantiation without parameters

I am new at using Autofac, so apologies if this is a stupid question.
Let's say I have an abstract class FooBase with parameterless constructor, and an implementation thereof called Foo.
In my AP.Net MVC5 client code, I would like to be able to create an instance of an object of type FooBase (I have set up Autofac to resolve it to Foo). The lifetime and scope of this instance is limited to my method, and I would like to do it in a fashion similar to calling a factory method if possible.
Currently I am making use of the DependencyResolver, but it seems a bit contrived. Is there a simpler way to do this?
For example, here is what it currently looks like...
public void SendMessage()
{
var foo = DependencyResolver.Current.GetService<FooBase>();
Debug.WriteLine(foo.Name);
}
I am looking for something a little more like this...
public void SendMessage()
{
var foo = IoC.Resolve<FooBase>();
Debug.WriteLine(foo.Name);
}
I think you can use delegate factories
First declare the delegate factory in the type that you want to build at runtime:
public class TestService
{
public delegate TestService Factory();
//other methods....
}
Then you can inject the factory as any other dependency, ex:
public class ExampleController
{
private TestService.Factory _factory;
public ExampleController(TestService.Factory factory)
{
_factory = factory;
}
public OtherMethod()
{
var serviceInstance = _factory();
}
}
Hope this helps!
Instead of using the Service Locator which is an anti-pattern, you can simply inject a factory which allows you to create an instance of the dependency if/when you want. The simplest way is to inject a Func<FooBase>. Autofac supports this natively. If you just register FooBase, AutoFac knows how to inject Func<FooBase>. Here is an example:
public class TestClass
{
private Func<FooBase> m_FooBaseFactory;
public TestClass(Func<FooBase> factory)
{
m_FooBaseFactory = factory;
}
public void TestMethod()
{
var foo = m_FooBaseFactory();
//consume foo here
}
}

Categories

Resources