Can you have generic create method for Zenject - c#

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

Related

Retrieve instantiated types from UnityContainer

(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>();

How implement Strategy/Facade Pattern using Unity Dependecy Injection Web API

How tell to Unity.WebApi dependency injection framework, inject the correct class in the correct controller?
DI Project Container
public class UnityContainerConfig
{
private static IUnityContainer _unityContainer = null;
public static IUnityContainer Initialize()
{
if (_unityContainer == null)
{
_unityContainer = new Microsoft.Practices.Unity.UnityContainer()
.RegisterType<IMyInterface, MyClass1>("MyClass1")
.RegisterType<IMyInterface, MyClass2>("MyClass2")
}
}
-MVC PROJECT-
public static class UnityConfig
{
public static void RegisterComponents()
{
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(DependencyInjection.UnityContainer.UnityContainerConfig.Initialize());
}
}
Controller 1:
private IMyInterface _myInterface
///MyClass1
public XController(
IMyInterface myInterface
)
{
_myInterface = myInterface
}
Controller 2:
private IMyInterface _myInterface
///MyClass2
public YController(
IMyInterface myInterface
)
{
_myInterface = myInterface
}
Rather than using a strategy or facade to solve this, a better solution would be to redesign your interfaces to be unique per controller. Once you have a unique interface type, your DI container will automatically inject the right service into each controller.
Option 1
Use a generic interface.
public interface IMyInterface<T>
{
}
public class XController
{
private readonly IMyInterface<XClass> myInterface;
public XController(IMyInterface<XClass> myInterface)
{
this.myInterface = myInterface;
}
}
public class YController
{
private readonly IMyInterface<YClass> myInterface;
public YController(IMyInterface<YClass> myInterface)
{
this.myInterface = myInterface;
}
}
Option 2
Use interface inheritance.
public interface IMyInterface
{
}
public interface IXMyInterface : IMyInterface
{
}
public interface IYMyInterface : IMyInterface
{
}
public class XController
{
private readonly IXMyInterface myInterface;
public XController(IXMyInterface myInterface)
{
this.myInterface = myInterface;
}
}
public class YController
{
private readonly IYMyInterface myInterface;
public YController(IYMyInterface myInterface)
{
this.myInterface = myInterface;
}
}

Get class type during dependency resoluton

When registering a type for my unity container, I need to pass in the calling class's type into the constructor of the resolved object.
This is the class where I am injecting some interfaces into the constructor.
namespace MyNamespace
{
internal class ProcessingService: IProcessingService
{
private readonly ISomeClass1 someClass1;
private readonly ISomeClass2 someClass2;
public ProcessingService(ISomeClass1 someClass1, ISomeClass2 someClass2)
{
this.someClass1 = someClass1;
this.someClass2 = someClass2;
}
}
}
SomeClass2 expects Type in the constructor:
public class SomeClass2
{
public SomeClass2(Type type)
{
//...
}
}
Here is my unity bootstrap class where I set up my container. Now, for ISomeClass2, when it resolves to SomeClass2, it needs to pass in the type of ProcessingService.
namespace MyNamespace
{
public class UnityBootstrap : IUnityBootstrap
{
public IUnityContainer Configure(IUnityContainer container)
{
return container
.RegisterType<ISomeClass1, SomeClass1>()
.RegisterType<ISomeClass2>(new InjectionFactory(fac =>
{
// IMethodBase.GetCurrentMethod().DeclaringType is returning MyNamespace.UnityBootstrap
// whereas I need to get MyNamespace.ProcessingService
return new SomeClass2(MethodBase.GetCurrentMethod().DeclaringType);
}));
}
}
}
Is there a way to do this using the InjectionFactory (or some other way within my Configure method)?
If you have control over the ProcessingService, you could create a generic wrapper around SomeClass2 and then register it using open generics. But that would require you modify the constructor of the ProcessingService.
public interface IGenericSomeClass2<T>: ISomeClass2 {}
public class GenericSomeClass2<T>: IGenericSomeClass2<T>
{
private readonly ISomeClass2 someClass2;
public GenericSomeClass2()
{
this.someClass2 = new SomeClass2(typeof(T));
}
// Pass-through implementation
}
public IUnityContainer Configure(IUnityContainer container)
{
return container
.RegisterType<ISomeClass1, SomeClass1>()
.RegisterType(typeof(IGenericSomeClass2<>), typeof(GenericSomeClass2<>));
}
internal class ProcessingService: IProcessingService
{
private readonly ISomeClass1 someClass1;
private readonly ISomeClass2 someClass2;
public ProcessingService(ISomeClass1 someClass1, IGenericSomeClass2<ProcessingService> someClass2)
{
this.someClass1 = someClass1;
this.someClass2 = someClass2;
}
}
IMHO, there are two points of view to this problem:
1) If SomeClass2 will always use the type ProcessingService then you can pass the type argument directly into the InjectionFactory
container.RegisterType<ISomeClass2>(new InjectionFactory(_ =>
{
return new SomeClass2(typeof(ProcessingService));
}));
2) Otherwise, if the type argument differs throughout application you should consider adding a registration method to interface ISomeClass2 and register the type from within the constructor to emphasize the dependency/variation.
public interface ISomeClass2
{
void DoSomething();
void RegisterProcessingServiceType(Type processingServiceType);
}
public class SomeClass2 : ISomeClass2
{
private Type _type;
public void DoSomething()
{
if(_type == null)
throw InvalidOperationException("Register processing service type before doing stuff.");
// actually do something
}
public void RegisterProcessingServiceType(Type serviceType)
{
_type = serviceType;
}
}
internal class ProcessingService: IProcessingService
{
private readonly ISomeClass1 someClass1;
private readonly ISomeClass2 someClass2;
public ProcessingService(ISomeClass1 someClass1, ISomeClass2 someClass2)
{
this.someClass1 = someClass1;
this.someClass2 = someClass2;
this.someClass2.RegisterProcessingServiceType(this.GetType());
}
}
If you do not control ProcessingService (or other consumers of SomeClass2), you could customize the registration of those consumers. This method is a bit more intrusive because you would have to create an injection factory for every consumer.
container
.RegisterType<IProcessingService, ProcessingService>(new InjectionFactory((c, type, name) =>
{
return new ProcessingService(c.Resolve<ISomeClass1>(), new SomeClass2(type));
}));

NSubstitute and Unity

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;

C# & Design Patterns - need an elegant solution for a common issue

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.

Categories