(Using Unity 4.0.1)
Given a UnityContainer object, is there any way to retrieve all the objects that have been instantiated by the container up to that point in time? E.g. something like
IEnumerable<object> instantiatedObjects = unityContainer.GetAllInstantiatedObjects();
or, even better, filtering according to those that derive from a given type:
IEnumerable<IFoo> instantiatedFoos = unityContainer.GetAllInstantiatedObjects<IFoo>();
Following RB's suggestion, the following approach implements a custom Unity extension with a strategy that keeps a reference to each instantiated object upon PostInitializtion.
N.B. The following code is for illustration only, and is not intended to be thread-safe/exception-safe etc.
First, the implementation of the Extension class and other classes it relies on.
public class ObjectContainer
{
private readonly List<object> _instantiatedObjects = new List<object>();
public void Add(object instantiatedObject)
{
_instantiatedObjects.Add(instantiatedObject);
}
public IEnumerable<object> GetInstantiatedObjects()
{
return _instantiatedObjects;
}
public IEnumerable<T> GetInstantiatedObjects<T>()
{
return GetInstantiatedObjects().OfType<T>();
}
}
public class InstantiatedObjectsStrategy : BuilderStrategy
{
private readonly ObjectContainer _objectContainer;
public InstantiatedObjectsStrategy(ObjectContainer objectContainer)
{
_objectContainer = objectContainer;
}
public override void PostBuildUp(IBuilderContext context)
{
_objectContainer.Add(context.Existing);
}
}
public class InstantiatedObjectsExtension : UnityContainerExtension
{
private readonly ObjectContainer _objectContainer = new ObjectContainer();
protected override void Initialize()
{
Context.Container.RegisterInstance(_objectContainer);
Context.Strategies.Add(new InstantiatedObjectsStrategy(_objectContainer),
UnityBuildStage.PostInitialization);
}
}
The extension can be added to the UnityContainer immediately after creation:
IUnityContainer container = new UnityContainer();
container.AddNewExtension<InstantiatedObjectsExtension>();
The instantiated objects can then be retrieved from the container at a later stage as follows:
IEnumerable<object> instantiatedObjects = container.Resolve<ObjectContainer>().GetInstantiatedObjects();
IEnumerable<Foo> instantiatedFoos = container.Resolve<ObjectContainer>().GetInstantiatedObjects<Foo>();
Related
Consider the code snippet (I used the strategy Pattern in the example) :
abstract class SortStrategy
{
public abstract void Sort(ArrayList list);
}
class QuickSort : SortStrategy
{
public override void Sort(ArrayList list)
{
//...
}
}
class ShellSort : SortStrategy
{
public override void Sort(ArrayList list)
{
// ....
}
}
and in Context :
class SortedList
{
private ArrayList list = new ArrayList();
private SortStrategy sortstrategy;
public void SetSortStrategy(SortStrategy sortstrategy)
{
this.sortstrategy = sortstrategy;
}
public void Add(string name)
{
list.Add(name);
}
public void Sort()
{
sortstrategy.Sort(list);
}
}
My question is that the end user through the UI and by selecting an option says to use the method for example QuickSort to sort, but what should I do, how to set SetSortStrategy (or how to dependency injection in this case)
I suggest using factory pattern with dependency injection:
public enum StrategyType
{
A,
B,
C
}
public interface IStrategyFactory {
IStrategy Create();
}
public class BasedOnUserSelStrategyFactory {
public IStrategy Create() {
StrategyType type = ReadUserSelectionFromFile(); // or any place stored
switch (type) {
case StrategyType.A:
return di.Resolve<AStrategy>(); // resolve using di container
case StrategyType.B:
return di.Resolve<BStrategy>(); // resolve using di container
case StrategyType.C:
return di.Resolve<CStrategy>(); // resolve using di container
default:
throw new ArgumentException("type");
}
}
}
Then, register factory in di:
di.Register<IStrategyFactory>().As<BasedOnUserSelStrategyFactory>();
Finally:
IStrategy s = di.Resolve<IStrategyFactory>().Create();
s.MyOperation();
The Castle.Windsor based DI of our MORYX-Framework allows users to configure a ModuleStrategy property in the config.
When a modules config looks like this:
public class ModuleConfig : ConfigBase
{
[DataMember, PluginStrategy(typeof(SortStrategy))]
[ModuleStrategy(typeof(SortStrategy))]
public string SortStrategy { get; set; }
}
The user can choose one of the found classes and every import of SortStragy is automatically filled with an instance. Using the graphic interface the user can select QuickSort and ShellSort, as well as any other implementation found at runtime from a drop-down box.
[Plugin(LifeCycle.Transient, typeof(SortStrategy))]
class QuickSort : SortStrategy
{
// ...
}
class SortedList
{
private ArrayList list = new ArrayList();
// injected with either QuickSort or ShellSort
public SortStrategy Sortstrategy { get; set; }
public void Add(string name)
{
list.Add(name);
}
public void Sort()
{
sortstrategy.Sort(list);
}
}
If you prefer to use the factory pattern, you can also declare a named factory. This can create any strategy registered as shown above.
[PluginFactory(typeof(INameBasedComponentSelector))]
public interface ISortStrategyFactory
{
SortStrategy Create(string name);
void Destroy(SortStrategy instance);
}
If you use Castle.Windsor, this is the code (Licensed under Apache2.0) we use to configure the override on all dependency declarations:
https://github.com/PHOENIXCONTACT/MORYX-Platform/blob/dev/src/Moryx.Container/LocalContainer/LocalRegistrator.cs#L34
So I have a base class and some derived classes, I want to have just one factory with generic create method witch will create appropriate instances and inject all dependencies. Is this possible using Zenject?
Something like.
factory.Create<Archer>()
For now I am doing this but as you see this is not very clean solution.
public class CustomFactory : IFactory<Type, BaseUnit>
{
private DiContainer _container;
public CustomFactory(DiContainer container)
{
_container = container;
}
public BaseUnit Create<Type>()
{
return null;
}
public BaseUnit Create(Type type)
{
if (type.BaseType != typeof(BaseUnit))
{
Debug.LogError("you cant create objects that are not derrived from base unit");
return null;
}
object obj = _container.Resolve(type) ;
return _container.InstantiatePrefabForComponent(type, obj as UnityEngine.Object, null, new object[0]) as BaseUnit;
}
}
I think the way you have it is probably the easiest way to do this. Here's some minor changes to what you did:
public class UnitFactory
{
readonly DiContainer _container;
readonly List<UnityEngine.Object> _prefabs;
public UnitFactory(
List<UnityEngine.Object> prefabs,
DiContainer container)
{
_container = container;
_prefabs = prefabs;
}
public BaseUnit Create<T>()
where T : BaseUnit
{
var prefab = _prefabs.OfType<T>().Single();
return _container.InstantiatePrefabForComponent<T>(prefab);
}
}
public class TestInstaller : MonoInstaller<TestInstaller>
{
public FooUnit FooPrefab;
public BarUnit BarPrefab;
public override void InstallBindings()
{
Container.Bind<UnitFactory>().AsSingle();
Container.Bind<UnityEngine.Object>().FromInstance(FooPrefab).WhenInjectedInto<UnitFactory>();
Container.Bind<UnityEngine.Object>().FromInstance(BarPrefab).WhenInjectedInto<UnitFactory>();
}
}
Only drawback with this approach is that the prefabs will not be validated, so if they have missing injections it won't be caught until runtime. The alternative would be to create individual factories for each BaseUnit, and then inject those factories into UnitFactory, but that would probably get messy
I am currently trying to learn DI & Mocking, with Unity and NSubstitute. I am also using an automocking extension taken from this question: Is this possible with Unity (Instead of Castle Windsor)?
In my unit test below I am trying to set an NSubstitute return value of 10 from my method Add(). However when debugging through the controller call the assigned value is the default 0 rather than the expected 10. The proxy does not seem to be intercepting the method call.
I suspect this is caused by not registering my Types/container correctly, anybody able to point me in the right direction?
[TestFixture]
public class ApplicationControllerTests
{
private IUnityContainer _container;
private ApplicationController _controller;
private ISampleService _sampleService;
[SetUp]
public void SetUp()
{
_container = new UnityContainer().AddExtension(new AutoMockingContainerExtension());
_controller = _container.Resolve<ApplicationController>();
_sampleService = _container.Resolve<ISampleService>();
}
[Test]
public void TestSampleService()
{
// This line is not working
_sampleService.Add(Arg.Any<int>(), Arg.Any<int>()).Returns(10);
var result = _controller.Index();
_sampleService.Received().Add(Arg.Any<int>(), Arg.Any<int>());
}
}
public class AutoMockingContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
var strategy = new AutoMockingBuilderStrategy(Container);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
class AutoMockingBuilderStrategy : BuilderStrategy
{
private readonly IUnityContainer _container;
public AutoMockingBuilderStrategy(IUnityContainer container)
{
_container = container;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface && !_container.IsRegistered(key.Type))
context.Existing = CreateSubstitute(key.Type);
}
private static object CreateSubstitute(Type type)
{
return Substitute.For(new[] { type }, null);
}
}
}
And my controller code
public class ApplicationController : BaseController
{
private readonly ISampleService _sampleService;
public ApplicationController(ISampleService sampleService)
{
_sampleService = sampleService;
}
public ActionResult Index()
{
var result = _sampleService.Add(2, 3);
// result is 0, expected 10 ??
return View();
}
}
public interface ISampleService
{
int Add(int first, int second);
}
public class SampleService : ISampleService
{
public int Add(int first, int second)
{
return first + second;
}
}
Actually Tormod is right the problem is that the AutoMockingBuilderStrategy returns a different mock instance every time when somebody requests an ISampleService form the container.
So there is a bug in my original implementation namely the AutoMockingBuilderStrategy doesn't store the created mocks:
Here is a fixed version:
public class AutoMockingContainerExtension : UnityContainerExtension
{
protected override void Initialize()
{
var strategy = new AutoMockingBuilderStrategy(Container);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
class AutoMockingBuilderStrategy : BuilderStrategy
{
private readonly IUnityContainer container;
private readonly Dictionary<Type, object> substitutes
= new Dictionary<Type, object>();
public AutoMockingBuilderStrategy(IUnityContainer container)
{
this.container = container;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface && !container.IsRegistered(key.Type))
{
context.Existing = GetOrCreateSubstitute(key.Type);
context.BuildComplete = true;
}
}
private object GetOrCreateSubstitute(Type type)
{
if (substitutes.ContainsKey(type))
return substitutes[type];
var substitute = Substitute.For(new[] {type}, null);
substitutes.Add(type, substitute);
return substitute;
}
}
}
I suspect that you are dealing with two different instances of ISampleService, created in lines 2 and 3 of Setup, respectively.
Could you, for test, make the _sampleServie field public and in the third Setup() line try
_sampleService = _controller._sampleService;
I have 2 projects : The first project is a structure project which i read from an xml file.
This project is used in other solutions
The second project(1 of the other solutions) work on the structure project with foreach running on components list:
namespace FriendProject.Workers
{
public class Worker
{
static void Main(string[] args)
{
foreach (Component component in ComponentList)
{
DoWork(component);
}
}
}
}
Today the DoWork method does the following:
public void DoWork(Component component)
{
// Doing work on component properties
// Zip component files with open source Zipper
if (component is DBComponent)
{
// work on DBComponent properties
}
}
Now if you are familiar with design patterns then you can see that there is an injection point here and the following should be done :
public class Component
{
public virtual void DoWork()
{
// Do work
}
}
public class DBComponent : Component
{
public override void DoWork()
{
base.DoWork();
// injection point - work on DBComponent properties
}
}
public class Operator
{
static void Main(string[] args)
{
foreach (Component component in ComponentList)
{
component.DoWork();
}
}
}
The problem is that the project which holds the Component and DBComponent is a structure project which is used in other solutions and with other projects and I need to add the open source Zip dll to the project and it becomes more tightly coupled to the current project("FriendProject") and less usable. Not to talk about that the other projects will never use these methods(DoWork in Component and DBComponent)
Is there a better solution without changing much the design? Should I add an adpater?
If so please provide and example.
Thanks to all
Edit: Short Question
2 projects :
One is a manager project which acts on the second project.
Second is a structure project(read data from xml) which is reused with other projects.
I want to add methods and refernces(since of polymorphism) in the structure project(second project). However it feels wrong since the other projects that uses it will never use those methods and the added references.
Is there a better solution for how to do it?
Edit :
Removed the structure project code the shorten the question. this code was irrelavent since its classes(Component and DBComponent) appear next.
Easy (and with three different GOF design patterns).
Since we can't do anything with the components, we'll have to use the bridge pattern.
Let's define handlers:
public interface IHandlerOf<T> where T : Component
{
void DoWork(T component);
}
So now we can create a handler type for each component type that we want to handle. A DB component handler would look like this:
public class DbComponentHandler : IHandlerOf<DbComponent>
{
public void DoWork(DbComponent component)
{
// do db specific information here
}
}
But since we don't really want to keep track of all handlers we'll want to create a class that does it for us. We ultimately want to invoke the code just as in your example:
foreach (Component component in ComponentList)
{
handler.DoWork(component);
}
But let's make it a bit cooler:
//maps handlers to components
var service = new ComponentService();
// register all handlers in the current assembly
service.Register(Assembly.GetExecutingAssembly());
// fake a component
var dbComponent = new DbComponent();
// the cool part, the invoker doesn't have to know
// about the handlers = facade pattern
service.Invoke(dbComponent);
The service with makes it possible looks like this:
public class ComponentService
{
private readonly Dictionary<Type, IHandlerInvoker> _handlers = new Dictionary<Type, IHandlerInvoker>();
public void Register(Assembly assembly)
{
foreach (var type in assembly.GetTypes())
{
if (type.IsInterface)
continue;
foreach (var interfaceType in type.GetInterfaces())
{
if (!interfaceType.IsGenericType || interfaceType.GetGenericTypeDefinition() != typeof(IHandlerOf<>))
continue;
var componentType = interfaceType.GetGenericArguments()[0];
var instance = Activator.CreateInstance(type);
var method = instance.GetType().GetMethod("DoWork", new[] { componentType });
_handlers[componentType] = new ReflectionInvoker(instance, method);
}
}
}
public void Register<T>(IHandlerOf<T> handler) where T : Component
{
_handlers[typeof (T)] = new DirectInvoker<T>(handler);
}
#region Nested type: DirectInvoker
private class DirectInvoker<T> : IHandlerInvoker where T : Component
{
private readonly IHandlerOf<T> _handler;
public DirectInvoker(IHandlerOf<T> handler)
{
_handler = handler;
}
#region IHandlerInvoker Members
public void Invoke(Component component)
{
_handler.DoWork((T) component);
}
#endregion
}
#endregion
#region Nested type: IHandlerInvoker
private interface IHandlerInvoker
{
void Invoke(Component component);
}
#endregion
#region Nested type: ReflectionInvoker
private class ReflectionInvoker : IHandlerInvoker
{
private readonly object _instance;
private readonly MethodInfo _method;
public ReflectionInvoker(object instance, MethodInfo method)
{
_instance = instance;
_method = method;
}
#region IHandlerInvoker Members
public void Invoke(Component component)
{
_method.Invoke(_instance, new object[] {component});
}
#endregion
}
#endregion
public void Invoke(Component component)
{
IHandlerInvoker invoker;
if (!_handlers.TryGetValue(component.GetType(), out invoker))
throw new NotSupportedException("Failed to find a handler for " + component.GetType());
invoker.Invoke(component);
}
}
Do note that the interface (IHandlerOf<T>) is generic which means that we can't store it directly in a Dictionary. Hence we use the Adapter pattern to store all handlers.
Full example:
public interface IHandlerOf<in T> where T : Component
{
void DoWork(T component);
}
public class ComponentService
{
private readonly Dictionary<Type, IHandlerInvoker> _handlers = new Dictionary<Type, IHandlerInvoker>();
public void Register(Assembly assembly)
{
foreach (var type in assembly.GetTypes())
{
if (type.IsInterface)
continue;
foreach (var interfaceType in type.GetInterfaces())
{
if (!interfaceType.IsGenericType || interfaceType.GetGenericTypeDefinition() != typeof(IHandlerOf<>))
continue;
var componentType = interfaceType.GetGenericArguments()[0];
var instance = Activator.CreateInstance(type);
var method = instance.GetType().GetMethod("DoWork", new[] { componentType });
_handlers[componentType] = new ReflectionInvoker(instance, method);
}
}
}
public void Register<T>(IHandlerOf<T> handler) where T : Component
{
_handlers[typeof (T)] = new DirectInvoker<T>(handler);
}
#region Nested type: DirectInvoker
private class DirectInvoker<T> : IHandlerInvoker where T : Component
{
private readonly IHandlerOf<T> _handler;
public DirectInvoker(IHandlerOf<T> handler)
{
_handler = handler;
}
#region IHandlerInvoker Members
public void Invoke(Component component)
{
_handler.DoWork((T) component);
}
#endregion
}
#endregion
#region Nested type: IHandlerInvoker
private interface IHandlerInvoker
{
void Invoke(Component component);
}
#endregion
#region Nested type: ReflectionInvoker
private class ReflectionInvoker : IHandlerInvoker
{
private readonly object _instance;
private readonly MethodInfo _method;
public ReflectionInvoker(object instance, MethodInfo method)
{
_instance = instance;
_method = method;
}
#region IHandlerInvoker Members
public void Invoke(Component component)
{
_method.Invoke(_instance, new object[] {component});
}
#endregion
}
#endregion
public void Invoke(Component component)
{
IHandlerInvoker invoker;
if (!_handlers.TryGetValue(component.GetType(), out invoker))
throw new NotSupportedException("Failed to find a handler for " + component.GetType());
invoker.Invoke(component);
}
}
public class DbComponent : Component
{
}
public class DbComponentHandler : IHandlerOf<DbComponent>
{
public void DoWork(DbComponent component)
{
// do db specific information here
Console.WriteLine("some work done!");
}
}
internal class Program
{
private static void Main(string[] args)
{
var service = new ComponentService();
service.Register(Assembly.GetExecutingAssembly());
var dbComponent = new DbComponent();
service.Invoke(dbComponent);
}
}
If you're sure you want to split data structure and data operations, create separate worker class.
public interface IWorker
{
void DoWork();
}
public abstract Worker<T>: IWorker where T: Component
{
private T _component;
protected Worker(T component) {_component = component;}
public abstract void DoWork();
}
public class DbWorker: Worker<DbComponent>
{
public DbWorker(DbComponent component): base(component) {}
public override DoWork() {...}
}
and implement some factory to create specific workers from specific components.
Have you considered having Operator and Component packaged together, and DBComponent in a second project, as for the other projecs of the solution ? Then, you could use a light container such as Spring.net to configure your .exe and load the relevant assemblies.
It is the right thing to give your Component behaviours instead of having the worker class manipulating its properties.
If you don't want other project to see the doWork method, hide it behind an public interface and create an adapter from the public interface to your internal one.
public interface ComponentPublic {
void sharedMethod();
}
public class ComponentPublicAdapter implement ComponentPublic {
private Component component;
void sharedMethod() {
// Do something, may be call doWork()
}
}
Package the ComponentPublic interface in a different project/namespace, therefore other projects may interact with it without knowing the internal interface. Use a dependency injection framework or reflection to instantiate the adapter and Components.
I've used Ninject with MVC3 for automagic inject of constructor arguments. It worked great.
How do you do something similar with non-MVC code.
For example:
public class Ninja
{
private readonly IWeapon _weapon;
public Ninja(IWeapon weapon)
{
_weapon = weapon;
}
public void Strike()
{
_weapon.Strike();
}
}
public class MyProgram
{
public void DoStuff()
{
var Ninja = new Ninja(); // I'm wanting Ninject to call the parameterized Ninja constructor
ninja.Strike();
}
}
How would I alter the code to get it to work?
public interface IWeapon
{
void Strike();
}
public class Sword : IWeapon
{
public void Strike()
{
Console.WriteLine("black ninja strike");
}
}
public class Ninja
{
private readonly IWeapon _weapon;
public Ninja(IWeapon weapon)
{
_weapon = weapon;
}
public void Strike()
{
_weapon.Strike();
}
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
Bind<IWeapon>().To<Sword>();
}
}
class Program
{
static void Main()
{
var kernel = new StandardKernel(new WarriorModule());
var ninja = kernel.Get<Ninja>();
ninja.Strike();
}
}
Wouldn't it just be:
var ninja = Kernel.Get<Ninja>();
You obviously have to resolve the dependency though Ninject.
You need to have an instance of StandardKernel let's call it kernel and then use kernel.Get<Ninja>(). This works since Ninja is non abstract, so it is considered bound to itself. Obviously some concrete types needs to be bound to IWeapon to allow NInject to create Ninja.