Lets say I have one Singleton that has one Scoped dependency (and is held by singleton forever).
Then I'm creating one scope and fetching both Singleton and Scoped instances from container.
I'd expect that Scoped is instantiated just once in a single scope.
Please have a look at a simplified code sample:
namespace TrivialConsole
{
using Microsoft.Extensions.DependencyInjection;
using System;
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddScoped<Scoped>();
services.AddSingleton<Singleton>();
var provider = services.BuildServiceProvider();
using (var rootScope = provider.CreateScope())
{
var scopeProvider = rootScope.ServiceProvider;
var singleton = scopeProvider.GetRequiredService<Singleton>();
var scoped = scopeProvider.GetRequiredService<Scoped>();
}
}
}
public class Singleton
{
private static int instances = 0;
private readonly Scoped scoped;
public Singleton(Scoped scoped)
{
instances += 1;
this.scoped = scoped;
Console.WriteLine($"singleton {instances}");
}
}
public class Scoped
{
private static int instances = 0;
public Scoped()
{
instances += 1;
Console.WriteLine($"scoped {instances}");
}
}
}
Results in:
scoped 1
singleton 1
scoped 2
Expected result ->
scoped 1
singleton 1
Scoped types are not suppose to be injected into singletons in this framework according to the documentation.
Do not resolve a scoped service from a singleton and be careful not to
do so indirectly, for example, through a transient service. It may
cause the service to have incorrect state when processing subsequent
requests. It's fine to:
Resolve a singleton service from a scoped or transient service.
Resolve a scoped service from another scoped or transient service.
Reference
Related
I have used Castle.DynamicProxy to create an interceptor that implements IInterceptor. This interceptor does some work related with logging.
I have successfully injected this into multiple classes using the default Microsoft Dependency Injection and I also was able to do so using Autofac.
Microsoft Dependency Injection:
public static void AddLoggedScoped<TService, TImplementation>(this IServiceCollection pServices)
where TService : class
where TImplementation : class, TService
{
pServices.TryAddScoped<IProxyGenerator, ProxyGenerator>();
pServices.AddScoped<TImplementation>();
pServices.TryAddTransient<LoggingInterceptor>();
pServices.AddScoped(provider =>
{
var proxyGenerator = provider.GetRequiredService<IProxyGenerator>();
var service = provider.GetRequiredService<TImplementation>();
var interceptor = provider.GetRequiredService<LoggingInterceptor>();
return proxyGenerator.CreateInterfaceProxyWithTarget<TService>(service, interceptor);
});
}
Autofac Dependency Injection:
builder.RegisterType<DITest>( ).As<IDITest>()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(LoggingInterceptorAdapter<LoggingInterceptor>));
Despite this I would also like to inject it in classes dynamically instantiated (for instances, classes that are instantiated accordingly to a value - factory pattern). My factory instantiates different concretizations of an interface depending on a value provided by parameter. Something along these lines:
public IApple Create(string color)
{
IApple fruit;
switch (color)
{
case "green":
fruit = new GreenApple();
break;
case "red":
fruit = new RedApple();
}
return fruit;
}
The interface IFruit looks like these:
public interface IFruit
{
void Cut();
void Eat();
string GetNutrionalInfo();
}
What I am trying to achieve is a way to inject/add an interceptor to the concretization of RedApple() that would allow me to know when methods such as redApple.Cut() are called.
What is the best way to do so? I was under the impression that Autofac would allow this, but I have not been successful.
What you will need to do is update your factory to use service location instead of directly constructing things. Basically, instead of using new, you'll need to use Autofac or Microsoft DI (assuming Autofac is configured as the backing container) to resolve the thing.
First, whenever you need your factory, make sure you are injecting it and not just calling new. Everything involved in this chain needs to go through Autofac.
public class UsesTheFactory
{
private IFactory _factory;
public UsesTheFactory(IFactory factory)
{
this._factory = factory;
}
}
You will, of course, need to register the thing that uses the factory.
builder.RegisterType<UsesTheFactory>();
Next, inject the lifetime scope into the factory and use it for service location. This is how you get the proxy and all that into the created objects.
public class MyFactory : IFactory
{
private readonly ILifetimeScope _scope;
public MyFactory(ILifetimeScope scope)
{
this._scope = scope;
}
public IApple Create(string color)
{
IApple fruit;
switch (color)
{
case "green":
fruit = this._scope.Resolve<GreenApple>();
break;
case "red":
fruit = this._scope.Resolve<RedApple>();
}
return fruit;
}
}
You'll need to register the factory and the things that the factory needs to resolve.
builder.RegisterType<MyFactory>().As<IFactory>();
builder.RegisterType<RedApple>();
builder.RegisterType<GreenApple>();
Finally, whenever you need something that uses the factory, that thing needs to be resolved. In this example, you can't really ever just new UsesTheFactory() - you have to resolve it (or have it injected into something else).
var builder = new ContainerBuilder();
builder.RegisterType<UsesTheFactory>();
builder.RegisterType<MyFactory>().As<IFactory>();
builder.RegisterType<RedApple>();
builder.RegisterType<GreenApple>();
var container = builder.Build();
using var scope = container.BeginLifetimeScope();
var user = scope.Resolve<UsesTheFactory>();
user.DoSomethingThatCallsTheFactory();
The key principle is that if you need that proxy injected anywhere in the pipeline, you can't use new. Full stop. If you need that thing, it needs to flow through Autofac somehow.
[This is for a Windows 10 IoT UWP app on a Raspberry Pi 2]:
Concretely, I'm trying to create two serial ports and link each one to a device driver for device that has a serial connection (I have two identical devices and a serial port to talk to each). I have a class (call it DeviceDriver) that implements an IDeviceDriver interface for this type of device. My hardware configuration also includes an external chip that has multiple serial ports. I have a class SerialPort for those and they implement an ISerialPort interface.
I need two instances of DeviceDriver as I have two devices, and two instances of SerialPort - one for each device. I can get Ninject to make one serialport and pass the ISerialPort object to the DeviceDriver constructor. Where I am stuck is that I want two DeviceDriver objects; one that gets linked to a SerialPort (COM1) and the other gets linked to a separate SerialPort (COM2). Examples for Ninject show you can bind multiple different classes to one instance (a Shuriken and Sword can both be bound to IWeapon), but I don't see how to bind a COM1 serialport and a COM2 serialport to ISerialPort - it gives me a compilation error. So how do I create two instances of the same SerialPort class (with different constructor arguments to say one is COM1 and the other is COM2, I know how to specify constructor arguments already) and then tell Ninject which SerialPort to pass to two instances of a DeviceDriver class, where one needs COM1 and one needs COM2?
My DeviceDriver basically looks like this:
public class DeviceDriver :IDeviceDriver
{
ISerialPort m_localPort;
public DeviceDriver(ISerialPort port)
{
m_localPort = port;
}
// Other stuff
// ...
}
Anybody have any thoughts how I can do this? The following link is the only thing I've found, but they are talking about Unity and XML configuration files and it seems overly complex for what I'm trying to do.
Initialising configurable objects with dependency injection container
Thanks!
Let's say we've got the following implementation:
public class SerialPortAddress
{
public SerialPortAddress(string address)
{
this.Address = address;
}
public string Address { get; }
}
public interface ISerialPort
{
SerialPortAddress Address { get; }
}
public class SerialPort : ISerialPort
{
public SerialPort(SerialPortAddress address)
{
this.Address = address;
}
public SerialPortAddress Address { get; }
}
public interface IDeviceDriver
{
ISerialPort SerialPort { get; }
}
public class DeviceDriver : IDeviceDriver
{
public DeviceDriver(ISerialPort serialPort)
{
SerialPort = serialPort;
}
public ISerialPort SerialPort { get; }
}
Multi-Injection
We can then create the bindings as follows and retrieve a list of IDeviceDrivers with their serial ports as follows:
public class Test
{
[Fact]
public void Bla()
{
var com1 = new SerialPortAddress("COM1");
var com2 = new SerialPortAddress("COM2");
var kernel = new StandardKernel();
kernel.Bind<ISerialPort>().To<SerialPort>();
kernel.Bind<IDeviceDriver>().To<DeviceDriver>()
.WithParameter(new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, target) => com1, true));
kernel.Bind<IDeviceDriver>().To<DeviceDriver>()
.WithParameter(new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, target) => com2, true));
var deviceDrivers = kernel.Get<List<IDeviceDriver>>();
deviceDrivers.Should().HaveCount(2)
.And.Contain(x => x.SerialPort.Address == com1)
.And.Contain(x => x.SerialPort.Address == com2);
}
}
Also see Multi Injection
Named Bindings
Alternatively, if you need to know which IDeviceDrivers is which, you can also use named bindings:
[Fact]
public void NamedBindings()
{
const string DeviceDriver1 = "DeviceDriver1";
const string DeviceDriver2 = "DeviceDriver2";
var com1 = new SerialPortAddress("COM1");
var com2 = new SerialPortAddress("COM2");
var kernel = new StandardKernel();
kernel.Bind<ISerialPort>().To<SerialPort>();
kernel.Bind<IDeviceDriver>().To<DeviceDriver>()
.Named(DeviceDriver1)
.WithParameter(new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, target) => com1, true));
kernel.Bind<IDeviceDriver>().To<DeviceDriver>()
.Named(DeviceDriver2)
.WithParameter(new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, target) => com2, true));
kernel.Get<IDeviceDriver>(DeviceDriver1).SerialPort.Address.Should().Be(com1);
kernel.Get<IDeviceDriver>(DeviceDriver2).SerialPort.Address.Should().Be(com2);
}
Factory
Finally, you could also create the components by factory, which requires a factory interface to begin with:
public interface IDeviceDriverFactory
{
IDeviceDriver Create(SerialPortAddress address);
}
using Ninject.Extensions.Factory we can now do the following:
[Fact]
public void Factory()
{
var com1 = new SerialPortAddress("COM1");
var com2 = new SerialPortAddress("COM2");
var kernel = new StandardKernel();
kernel.Bind<ISerialPort>().To<SerialPort>();
kernel.Bind<IDeviceDriver>().To<DeviceDriver>();
kernel.Bind<IDeviceDriverFactory>()
.ToFactory(() => new TypeMatchingArgumentInheritanceInstanceProvider());
var factory = kernel.Get<IDeviceDriverFactory>();
factory.Create(com1).SerialPort.Address.Should().Be(com1);
factory.Create(com2).SerialPort.Address.Should().Be(com2);
}
EDIT: Ninject.Extension.Factory may not run on the raspberry pi.
If that's the case you might need to implement the factory yourself:
public class DeviceDriverFactory : IDeviceDriverFactory
{
private readonly IResolutionRoot resolutionRoot;
public DeviceDriverFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IDeviceDriver Create(SerialPortAddress address)
{
var serialPortAddressParameter = new TypeMatchingConstructorArgument(
typeof(SerialPortAddress),
(ctx, t) => address)
this.resolutionRoot.Get<IDeviceDriver>(serialPortAddressParameter);
}
}
Bind<IDeviceDriverFactory>().To<DeviceDriverFactory>();
I'm not familiar Ninject or Unity, but Castle Windsor has a lifestyle called Pooled, which will create up to a specified number of instances and then return those instances to the pool of instances after they've been released. When using this lifestyle, Windsor will create as many objects as are requested up to the limit specified, and then either recycle the instance (if you've derived from IRecyclable and implemented the Recycle() method) or dispose of it normally.
You can have your components created using a simple factory method that provides the correct constructor arguments, and then when they are returned to the pool they will be correctly configured.
EDIT:
If you're set on using Ninject, then I would solve this problem by injecting an ISerialPortFactory into the constructor of DeviceDriver and using that to create your ISerialPort objects. Since your DeviceDriver class doesn't care which ISerialPort it's using, the factory can be used to manage the instances that you need.
Your factory would look something like this:
public interface ISerialPortFactory
{
ISerialPort CreateNext();
}
public class SerialPortFactory : ISerialPortFactory
{
public ISerialPort CreateNext()
{
var serialPortConfiguration = GetNextConfiguration();
return new SerialPort(serialPortConfiguration);
}
private GetNextConfiguration()
{
// you could manage some kind of internal registry of COMx configurations here
}
}
And your client DeviceDriver class would look like this:
public class DeviceDriver : IDeviceDriver
{
public DeviceDriver(ISerialPortFactory factory)
{
m_localPort = factory.CreateNext();
}
}
The abstract factory method is sort of a heavy-handed way of getting what you want, but it's a surefire way to get exactly what you need since you have complete control over it. Its main use case is to resolve dependencies where you don't necessarily know the exact implementation you want until runtime.
We inject IQueryHandler<TQUery,TResult> into our MVC controllers. We globally register all of these in the container
We have written a decorator that can cache the results of IQueryHandler.
We want to sometimes get cached reults and other times not from the same handler.
Is it possible to conditionally get a decorated handler based on the name of the constructor parameter. e.g. inject IQueryHandler<UnemployedQuery, IEnumerable<People>> cachedPeopleHandler if we prefix constructor parameter name with cached we actually get it wrapped with decorator?
Just trying to use a more convention over configuration approach to simplify things.
Yes it's possible to do it. Below is a simple working example on how you can achieve it:
class Program
{
public interface IQueryHandler{}
private class QueryHandler : IQueryHandler
{
}
private class CacheQueryHandler : IQueryHandler
{
}
public interface IService
{
}
private class Service : IService
{
private readonly IQueryHandler _queryHandler;
private readonly IQueryHandler _cacheQueryHandler;
public Service(IQueryHandler queryHandler, IQueryHandler cacheQueryHandler)
{
_queryHandler = queryHandler;
_cacheQueryHandler = cacheQueryHandler;
}
public override string ToString()
{
return string.Format("_queryHandler is {0}; _cacheQueryHandler is {1}", _queryHandler,
_cacheQueryHandler);
}
}
static void Main(string[] args)
{
var builder = new ContainerBuilder();
// Register the dependency
builder.RegisterType<QueryHandler>().As<IQueryHandler>();
// Register the decorator of the dependency
builder.RegisterType<CacheQueryHandler>().Keyed<IQueryHandler>("cache");
// Register the service implementation
builder.RegisterType<Service>().AsSelf();
// Register the interface of the service
builder.Register(c =>
{
var ctor = typeof (Service).GetConstructors()[0];
var parameters =
ctor.GetParameters()
.Where(p => p.Name.StartsWith("cache"))
.Select(p => new NamedParameter(p.Name, c.ResolveKeyed("cache", p.ParameterType)));
return c.Resolve<Service>(parameters);
}).As<IService>();
using (var container = builder.Build())
{
var service = container.Resolve<IService>();
Console.WriteLine(service.ToString());
Console.ReadKey();
}
}
}
Update:
Basically you need to:
1. Think up a general convention. Prefix "cache" of ctor parameter name in your case.
2. Register your dependencies as usual.
3. Register your decorators, so they don't overwrite your original dependencies and you can easily resolve them basing on your convention. e.g. Keyed, Named, via Attribute, etc.
4. Register you actual implementation of class that uses decorators
5. Register your interface that describes the class via lambda expression that has all magic inside.
Note: I provided just a simple and working example. It's on you to make it nice, easy to use and fast e.g. make it as an extension, generic, cache reflection results etc. It's not difficult anyway.
Thanks.
I'm working on an ASP.NET MVC project that support external plugins, now, I'm moving from Unity to Autofac and I need to wrap the lifetime objects of Autofac so the plugins won't have to reference it, in Unity I could do something this.
public sealed class UnityScopeFactory : IDependencyScopeFactory
{
private HttpRequestScope _httpRequest;
private SingletonScope _singleton;
private TransientScope _transient;
public IDependencyScope HttpRequest()
{
return _httpRequest ?? (_httpRequest = new HttpRequestScope());
}
public IDependencyScope Singleton()
{
return _singleton ?? (_singleton = new SingletonScope());
}
public IDependencyScope Transient()
{
return _transient ?? (_transient = new TransientScope());
}
private class HttpRequestScope : IDependencyScope
{
public object CreateScope()
{
return new HttpPerRequestLifetimeManager();
}
}
private class SingletonScope : IDependencyScope
{
public object CreateScope()
{
return new ContainerControlledLifetimeManager();
}
}
private class TransientScope : IDependencyScope
{
public object CreateScope()
{
return new TransientLifetimeManager();
}
}
}
I made similar thing in Autofac but I'm not sure whether it's the correct way to do that, I looked into the RegistrationBuilder of Autofac which is (unfortunately) internal and I came up with this.
public class AutofacScopeFactory : IDependencyScopeFactory
{
private HttpRequestScope _httpRequest;
private SingletonScope _singleton;
private TransientScope _transient;
public IDependencyScope HttpRequest()
{
return _httpRequest ?? (_httpRequest = new HttpRequestScope());
}
public IDependencyScope Singleton()
{
return _singleton ?? (_singleton = new SingletonScope());
}
public IDependencyScope Transient()
{
return _transient ?? (_transient = new TransientScope());
}
private class HttpRequestScope : IDependencyScope
{
public object CreateScope()
{
return new CurrentScopeLifetime();
}
}
private class SingletonScope : IDependencyScope
{
public object CreateScope()
{
return new RootScopeLifetime();
}
}
private class TransientScope : IDependencyScope
{
public object CreateScope()
{
return new CurrentScopeLifetime();
}
}
}
Also, after I got this to work, how can I use pass it to the ContainerBuilder?
In Unity I could do something like this.
public sealed class UnityDependencyContainer : IDependencyContainer
{
private readonly IUnityContainer _container;
public UnityDependencyContainer()
{
_container = new UnityContainer()
}
public void Register<TContract, TImplementation>(IDependencyScope scope) where TImplementation : TContract
{
LifetimeManager manager = scope.CreateScope() as LifetimeManager;
if (manager != null)
{
_container.RegisterType<TContract, TImplementation>(manager);
}
}
}
How do I pass an instance of IComponentLifetime to the method chain? is it a dead end?
public class AutofacContainer : IDependencyContainer
{
private static readonly ContainerBuilder Builder;
static AutofacContainer()
{
Builder = new ContainerBuilder();
}
public void RegisterType<TContract, TImplementation>(IDependencyScope scope) where TImplementation : TContract
{
IComponentLifetime manager = scope.CreateScope() as IComponentLifetime;
if (manager != null)
{
Builder.RegisterType<TImplementation>().As<TContract>();
}
}
}
Autofac doesn't separate scopes quite the way you have it outlined, so you might be trying to fit a square peg in a round hole.
Autofac scopes are more hierarchical. Any lifetime scope can spawn a child transient scope. For example, you might see...
Container/root lifetime
HttpRequest scope
Small task-specific transient scope
You can "tag" a scope and register components to a specific named/tagged scope - that's how the HttpRequest scope works. It gets "tagged" with a special identifier.
When you resolve objects is when it determines which lifetime scope owns it. Resolving happens from the most-nested scope. In the above hierarchy, you resolve items from the small task-specific transient scope whether they're singletons, request scoped, or whatever. When the singleton gets resolved, it will search up the lifetime scope stack and automatically assign "ownership" of the object to the root lifetime scope. When a per-request item gets resolved, it searches up the stack for the lifetime scope with the special "HTTP request" identifier and assigns ownership there. Factory-scoped items are resolved in the current lifetime scope.
Note: That discussion is a gross oversimplification of how it works. There is documentation explaining the lifetime scope mechanism on the Autofac site.
Point being, I see some things in the above design that don't really "jive" with the way Autofac does stuff.
The DependencyScopeFactory can't create its own transient or HttpRequest scopes. There are specific lifetime management components that start and end the HttpRequest scope, so you'd need to use those; there is no 'global' transient scope, so you can't really just create one.
HttpRequest scope, assuming you're using MVC, would look more like...
public ILifetimeScope HttpRequestScope
{
get { return AutofacDependencyResolver.Current.RequestLifetime; }
}
There's no analog for a transient scope because usage on that is supposed to be inline:
using(var transientScope = parentScope.BeginLifetimeScope())
{
// Do stuff and resolve dependencies using the transient scope.
// The IDisposable pattern here is important so transient
// dependencies will be properly disposed at the end of the scope.
}
When you register components, you don't register them "into a lifetime scope." You actually register them into a component registry and part of the component registration includes the ownership information about the lifetime of the component once it's resolved.
var builder = new ContainerBuilder();
// This component is factory-scoped and will be "owned" by whatever
// lifetime scope resolves it. You can resolve multiple of these
// in a single scope:
builder.RegisterType<FirstComponent>().As<ISomeInterface>();
// This component is a singleton inside any given lifetime scope,
// but if you have a hierarchy of scopes, you'll get one in each
// level of the hierarchy.
builder.RegisterType<SecondComponent>().InstancePerLifetimeScope();
// This component will be a singleton inside a specifically named
// lifetime scope. If you try to resolve it in a scope without that
// name, it'll search up the scope stack until it finds the scope
// with the right name. If no matching scope is found - exception.
builder.RegisterType<ThirdComponent>().InstancePerMatchingLifetimeScope("scopename");
// This is a per-HTTP-request component. It's just like the
// above InstancePerMatchingLifetimeScope, but it has a special
// tag that the web integration knows about.
builder.RegisterType<FourthComponent>().InstancePerHttpRequest();
If you're trying to make a container/registration agnostic interface, it wouldn't need a "lifetime scope manager" - instead, you'd need to pass some parameters indicating the intended lifetime scope and do the appropriate registration syntax (above) based on the incoming parameters.
Again, I'd recommend you check out that documentation.
Also, if you're using Unity, Autofac does have an Enterprise Library Configurator package that allows you to configure Autofac in a Unity style (since that's how EntLib likes to do things). That might be something to check out.
If you don't need to use Unity syntax at all... I'd recommend just moving to do things the native Autofac way. Trying to make one container look and act like another is a pretty painful endeavor.
Assuming your plugins are in separate assemblies or whatever, you could easily take advantage of some of the nice assembly-scanning syntax along with Autofac modules and hook up your plugins that way.
Imagine there is a Customer class with an instance Load() method.
When the Load() method is called, it retrieves order details by e.g.
var orders = Order.GetAll(customerId, ...);
GetAll() is a static method of the Order class and the input parameters are fields defined in the Customer class.
As you can see, Order is a dependency of the Customer class, however, I can't just create an IOrder and inject it there as interfaces can't have static methods.
Therefore, the question is how could I introduce dependency injection in this example?
I don't want to make GetAll() an instance method since it's a static method and need to keep it that way.
For example, I have used utility classes in my design, most of which just contain static methods.
If you must keep the static method, I would wrap the static calls in a Repository object.
Like this:
interface IOrderRepository {
IEnumerable<IOrder> GetAll(customerId, ..);
}
class OrderRepository : IOrderRepository {
IEnumerable<IOrder> GetAll(customerId, ...)
{
Order.GetAll(customerId,...); // The original static call.
}
}
Now you inject this repository into your Customer class.
(I'm assuming you're doing this so you can inject fake IOrders at runtime for testing purposes. I should say that in general, static methods are a serious obstacle to testing.)
Seeing as your aggregate root for fetching orders is your customer model I would strongly advise you create a customer repository and inject that to whatever service requires it.
Here is an example:
public class CustomerService
{
private readonly ICustomerRepository _customerRepository;
public CustomerService(ICustomerRepository customerRepository)
{
if (customerRepository == null)
{
throw new ArgumentNullException("customerRepository");
}
_customerRepository = customerRepository;
}
public IEnumerable<IOrder> GetOrdersForCustomerId(int customerId)
{
return _customerRepository.GetOrdersForCustomerId(customerId);
}
}
public interface ICustomerRepository
{
IEnumerable<IOrder> GetOrdersForCustomerId(int customerId);
}
class CustomerRepository : ICustomerRepository
{
public IEnumerable<IOrder> GetOrdersForCustomerId(int customerId)
{
throw new NotImplementedException();
}
}
Function Pointer Injection
TLDR:
Inject a function pointer into the Customer class. The value of this function pointer can be Order.GetAll in production, and MockOrder.GetAll in tests.
EXAMPLE:
The dependency (problematic static function we depend on):
class Order {
static func GetAll() -> [Order] {
var orders = ... // Load from production source
return orders
}
}
Our dependent class (depends on static function):
class Customer {
func Init(getAllOrdersFunction) { // Arg is a func pointer
self.getAllOrdersFunction = getAllOrdersFunction
}
func Load() {
var orders = self.getAllOrdersFunction()
// Do stuff...
}
}
Production client class (performs the dependency injection):
class BusinessLogicManager {
func DoBusinessLogic() {
var customer = Customer(Order.GetAll) // Prod func injected here
customer.Load()
// Do stuff...
}
}
Testing client class (how unit test can inject a fake dependency):
class CustomerUnitTests {
static func GetFakeOrders() {
var orders = ... // Hardcoded test data
return orders
}
func TestLoad() {
var customer = Customer(CustomerUnitTests.GetFakeOrders) // Fake func injected here
customer.Load()
// Verify results given known behavior of GetFakeOrders
}
}
DISCUSSION:
How you actually inject the "function pointer" will depend on the syntax and features available in your language. Here I'm just talking about the general concept.
This isn't exactly a pretty solution. It would probably be easier if you can change GetAll to be an instance method (perhaps by introducing an OrdersLoader object, or by using Paul Phillips' answer). But if you really want to keep it as a static function, then this solution will work.