In my application I've noticed that if I mark a class in the SM registry as a Singleton type it gets disposed of, however if don't specify any Singleton it doesn't get disposed of.
What and why are the reasons for this?
public class IoC
{
public static IContainer Init()
{
var container = new Container(x =>
{
x.Scan(s => {
s.TheCallingAssembly();
s.AssembliesFromApplicationBaseDirectory();
s.WithDefaultConventions();
});
// disposed is called on this class but not if .Singleton() is removed
x.For<IMyService>().Singleton();
});
return container;
}
}
class Program
{
static void Main(string[] args)
{
using (var container = IoC.Init())
{
var theStory1 = container.GetInstance<MyService>();
theStory1.TheMethod();
}
}
}
Singleton lifecycle is bound to the container's scope thus when disposing the container it takes care to dispose all singletons implementing IDisposable. With transients and other lifecycles like HttpContextScoped it is up to developer to dispose them manually when no longer need them.
Transient disposables are tricky a little bit in terms of how it should be handled. Imagine case like this one below:
public class ClassWithDisposableTypeDependency
{
private readonly ISampleDisposable disposableType;
public ClassWithDisposableTypeDependency(ISampleDisposable disposableType)
{
this.disposableType = disposableType;
}
public void SomeAction()
{
using (this.disposableType)
{
this.disposableType.DoSomething();
}
}
}
What will happend when SomAction() won't be executed? Dispose won't be called on disposableType field. In fact in this case ClassWithDisposableTypeDependency should also implement IDisposable and dispose its disposable dependencies.
But there is a better way to handle such cases. In mentioned case the main issue is to defer creation of a dependency to a moment when we really need that objects. We can achieve that in many ways: func, lazy, factory, etc. Here is possible solution with usage of func.
public class ClassWithDisposableTypeFuncDependency
{
private readonly Func<ISampleDisposable> disposableTypeFactory;
public ClassWithDisposableTypeFuncDependency(Func<ISampleDisposable> disposableTypeFactory)
{
this.disposableTypeFactory = disposableTypeFactory;
}
public void SomeAction()
{
var disposable = this.disposableTypeFactory();
using (disposable)
{
disposable.DoSomething();
}
}
}
This is how we need to setup it in StructureMap:
var container = new Container(c => c.For<ISampleDisposable>().Use<SampleDisposable>());
var clazz = container.GetInstance<ClassWithDisposableTypeFuncDependency>();
clazz.SomeAction(); // dependency is created and disposed
Hope this helps!
Related
I need to get dependencies in class that implements yii\queue\Job interface. In perfect world I would do something like this:
public function __construct(SomeInterface $service)
{
$this->service = $service;
}
public function execute($queue)
{
$this->service->doSomething();
}
Unfortunately yii2-queue doesn't support resolving dependencies in job handler constructor. For now I deal with it like this:
public function execute($queue)
{
$service = Yii::$container->get(SomeInterface::class);
$service->doSomething();
}
Maybe there is a cleaner way to do this?
I dealt with it using factory method pattern and resolving dependencies from DI container in it. Altought there are some problems with serialization of heavy dependecies. To resolve that I used simple proxy.
$this->queue->push(FooJob::create($someId));
// (...)
class FooJob implements Job
{
public $id;
private $fooService;
private $heavyService;
public function __construct(int $id, FooInterface $fooService)
{
$this->fooService = $fooService;
}
public static function create(int $id): self
{
return Yii::$container->get(static::class, [$id]);
}
public function execute(Queue $queue): void
{
$this->fooService->bar($this->id); // service available since construct
$this->heavyService->bark($this->id); // service available since first call
}
public function getHeavyService(Queue $queue): HeavyInterface
{
if (!$this->heavyService) {
$this->heavyService = Yii::$container->get(HeavyServiceInterface::class);
}
return $this->heavyService;
}
}
This is way more clean approach than one I used before. It's not perfect, but with Yii limitations its enough.
For an Azure Service Fabric stateful service it is possible to inject the IReliableStateManager as follows:
ServiceRuntime.RegisterServiceAsync("MyServiceType", context =>
{
IReliableStateManager stateManager = new ReliableStateManager(context);
return new MyService(stateManager);
}
And this way you can mock IStateManager in unit tests for MyService.
The same doesn't seem possible for a stateful actor. IActorStateManager only has an internal implementation: Microsoft.ServiceFabric.Actors.Runtime.ActorStateManager. So how do I unit test a stateful actor?
At some point in my actor methods a call is made to IActorStateManager but since I can't inject this dependency, unit tests seem impossible.
Is there some way to work around this or is there another solution?
No, IActorStateManager isn't injectable today, but we're working on making it so. For now (without using reflection) you'll have to wrap your state operations in something that you can inject, and have that call into the state manager, which you can then mock for unit testing.
I usually write actor business logic in separate class that have constructor with IStateManager parameter and implement my actor interface. Actor is just wrapper around actor implementation class and I test actorImpl class instead of actor. Look at the code:
public interface IMyActor01 : IActor
{
Task<int> GetCountAsync();
Task SetCountAsync(int count);
}
public class MyActor01Impl : IMyActor01
{
private readonly IActorStateManager StateManager;
public MyActor01Impl(IActorStateManager stateManager)
{
this.StateManager = stateManager;
this.StateManager.TryAddStateAsync("count", 0);
}
public Task<int> GetCountAsync()
{
return this.StateManager.GetStateAsync<int>("count");
}
public Task SetCountAsync(int count)
{
return this.StateManager.AddOrUpdateStateAsync("count", count, (key, value) => count > value ? count : value);
}
}
[StatePersistence(StatePersistence.Persisted)]
internal class MyActor01 : Actor, IMyActor01
{
private MyActor01Impl Impl;
protected override Task OnActivateAsync()
{
ActorEventSource.Current.ActorMessage(this, "Actor activated.");
this.Impl = new MyActor01Impl(this.StateManager);
return Task.FromResult(true);
}
Task<int> IMyActor01.GetCountAsync()
{
return this.Impl.GetCountAsync();
}
Task IMyActor01.SetCountAsync(int count)
{
return this.Impl.SetCountAsync(count);
}
}
[TestFixture]
public class TestFixture01
{
[Test]
public void Test01()
{
//ARRANGE
var dictionary = new Dictionary<string, object>();
var impl = new MyActor01Impl(new StubStateManager(dictionary));
//ACT
impl.SetCountAsync(12).Wait();
//ASSERT
Assert.AreEquals(12, impl.GetCountAsync().Result);
//or
Assert.AreEquals(12, (int)dictionary["count"]);
}
}
I can share StubStateManager implementation if you want.
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.
I'm getting some very unexpected (I think) behavior with the Typed Factory facility. Basically, it's reusing transient component instances for constructor injection with Func<T>.
Here is the gist of it:
// this guy is registered as service EntityFrameworkRepositoryProvider, not IRepository
[Transient]
public class EntityFrameworkRepositoryProvider : IRepository
{
public EntityFrameworkRepositoryProvider(ObjectContext objectContext, Assembly assembly)
{
// HOLY MOLY BATMAN!! Every time I hit this constructor when getProvider gets called,
// I don't actually get the arguments passed into getProvider. I get the
// arguments that were passed into getProvider the very FIRST time
// it was called...in other words I get the wrong
// ObjectContext (for the wrong connection string)...BIG PROBLEM
// do stuff...
}
}
[Singleton]
// this guy gets registered on startup
internal class EntityFrameworkRepositoryProviderFactory : IRepositoryProviderFactory
{
private readonly Func<ObjectContext, Assembly, EntityFrameworkRepositoryProvider> getProvider;
public EntityFrameworkRepositoryProviderFactory(Func<ObjectContext, Assembly, EntityFrameworkRepositoryProvider> getProvider)
{
this.getProvider = getProvider;
// do stuff...
}
public IRepository CreateRepository()
{
var provider = getProvider(new ObjectContext(GetConnectionString()),
Assembly.GetExecutingAssembly);
// do stuff...
}
public string GetConnectionString()
{
// returns one of a few diff EF connection strings
}
}
I also have a standard LazyComponentLoader. What am I doing wrong here? What should I do instead?
Thanks.
Problem was this seemingly harmless code in the LazyComponentLoader:
public IRegistration Load(string key, Type service, IDictionary arguments)
{
var component = Component.For(service);
if (!string.IsNullOrEmtpy(key))
{
component = component.Named(key);
}
if (arguments != null)
{
// This makes the typed factory facility screw up. (Merge is an extension method that merges dictionaries)
component.DynamicParameters((k, d) => d.Merge(arguments));
}
return component;
}
public static void Merge(this IDictionary target, IDictionary source)
{
foreach (object key in source.Keys)
{
target[key] = source[key];
}
}
How do I handle classes with static methods with Ninject?
That is, in C# one can not have static methods in an interface, and Ninject works on the basis of using interfaces?
My use case is a class that I would like it to have a static method to create an
unpopulated instance of itself.
EDIT 1
Just to add an example in the TopologyImp class, in the GetRootNodes() method, how would I create some iNode classes to return? Would I construct these with normal code practice or would I somehow use Ninject? But if I use the container to create then haven't I given this library knowledge of the IOC then?
public interface ITopology
{
List<INode> GetRootNodes();
}
public class TopologyImp : ITopology
{
public List<INode> GetRootNodes()
{
List<INode> result = new List<INode>();
// Need code here to create some instances, but how to without knowledge of the container?
// e.g. want to create a few INode instances and add them to the list and then return the list
}
}
public interface INode
{
// Parameters
long Id { get; set; }
string Name { get; set; }
}
class NodeImp : INode
{
public long Id
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public string Name
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
// Just background to highlight the fact I'm using Ninject fine to inject ITopology
public partial class Form1 : Form
{
private ITopology _top;
public Form1()
{
IKernel kernal = new StandardKernel(new TopologyModule());
_top = kernal.Get<ITopology>();
InitializeComponent();
}
}
If you're building a singleton or something of that nature and trying to inject dependencies, typically you instead write your code as a normal class, without trying to put in lots of (probably incorrect) code managing the singleton and instead register the object InSingletonScope (v2 - you didnt mention your Ninject version). Each time you do that, you have one less class that doesnt surface its dependencies.
If you're feeling especially bloody-minded and are certain that you want to go against that general flow, the main tools Ninject gives you is Kernel.Inject, which one can use after you (or someone else) has newd up an instance to inject the dependencies. But then to locate one's Kernelm you're typically going to be using a Service Locator, which is likely to cause as much of a mess as it is likely to solve.
EDIT: Thanks for following up - I see what you're after. Here's a hacky way to approximate the autofac automatic factory mechanism :-
/// <summary>
/// Ugly example of a not-very-automatic factory in Ninject
/// </summary>
class AutomaticFactoriesInNinject
{
class Node
{
}
class NodeFactory
{
public NodeFactory( Func<Node> createNode )
{
_createNode = createNode;
}
Func<Node> _createNode;
public Node GenerateTree()
{
return _createNode();
}
}
internal class Module : NinjectModule
{
public override void Load()
{
Bind<Func<Node>>().ToMethod( context => () => Kernel.Get<Node>() );
}
}
[Fact]
public void CanGenerate()
{
var kernel = new StandardKernel( new Module() );
var result = kernel.Get<NodeFactory>().GenerateTree();
Assert.IsType<Node>( result );
}
}
The ToMethod stuff is a specific application of the ToProvider pattern -- here's how you'd do the same thing via that route:-
...
class NodeProvider : IProvider
{
public Type Type
{
get { return typeof(Node); }
}
public object Create( IContext context )
{
return context.Kernel.Get<Node>();
}
}
internal class Module : NinjectModule
{
public override void Load()
{
Bind<Func<Node>>().ToProvider<NodeProvider>();
}
}
...
I have not thought this through though and am not recommending this as A Good Idea - there may be far better ways of structuring something like this. #Mark Seemann? :P
I believe Unity and MEF also support things in this direction (keywords: automatic factory, Func)
EDIT 2: Shorter syntax if you're willing to use container-specific attributes and drop to property injection (even if Ninject allows you to override the specific attributes, I much prefer constructor injection):
class NodeFactory
{
[Inject]
public Func<Node> NodeFactory { private get; set; }
public Node GenerateTree()
{
return NodeFactory();
}
}
EDIT 3: You also need to be aware of this Ninject Module by #Remo Gloor which is slated to be in the 2.4 release
EDIT 4: Also overlapping, but not directly relevant is the fact that in Ninject, you can request an IKernel in your ctor/properties and have that injected (but that doesn't work directly in a static method).