I am using Guice for assisted injection. Here is a standard scenario:
Class TargetType {
#Inject
TargetType(#Assisted Param1 assistedParam, InjectedType injectedType)
{
/* ... */
}
}
Class InjectedType {
#Inject
injectedType(OtherInjectedType otherInjectedType)
{
/* ... */
}
}
Now I could use Guice factory to call TargetTypeFactory.create(assistedArg /* instanceof Param1 */) and happily obtain my instance of TargetType with instance of InjectedType injected by Guice.
My problem is: what if I want for the InjectedType to have reference to the instance of the TargetType being created? In other words, I want:
Class TargetType {
#Inject
TargetType(#Assisted Param1 assistedParam, InjectedType injectedType)
{
}
}
Class InjectedType {
#Inject
injectedType(/* How to get this? -> */ TargetType constructedTargetType, OtherInjectedType otherInjectedType)
{
}
}
My current workaround is quite ugly: I create a TargetType manually without the InjectedType, then I use InjectedTypeFactory to get the InjectedType instance and call the setInjectedType(InjectedType) method on the TargetType instance. Ungh!
Interesting problem. I don't think that there's a totally clean solution to this, but maybe this solution based on child injectors will work for you:
First, create a custom guice binding annotation for your own use:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.PARAMETER})
#BindingAnnotation
public #interface JamrozikParam {}
Then, change TargetType to look like this:
class TargetType {
#Inject
TargetType(#JamrozikParam Param1 assistedParam, InjectedType injectedType)
{
}
}
Leave InjectedType as it was.
Now, this is how you get an instance of TargetType:
Injector topInjector = Guice.createInjector(/* Your modules here */);
// Note that the modules used there can't mention TargetType or InjectedType
// Now many lines later
Param1 myP1val;
myP1val = // ... however that was computed
Injector childInjector = topInjector.childInjector(new Param1Module(myP1val));
TargetType t1 = childInjector.getInstance(TargetType.class);
Where Param1Module is a class that looks like:
public class Param1Module extends AbstractModule {
private final Param1 p1val;
public Param1Module(Param1 p1val) {this.p1val = p1val;}
protected void configure() {
bind(Param1.class).annotatedWith(JamrozikParam.class).toInstance(p1val);
bind(TargetType.class).in(Singleton.class);
bind(InjectedType.class).in(Singleton.class);
}
}
Note that in order for this to work, Guice is going to be creating a proxy to work around the circular dependency. I suggest that you make its job of proxy creation easier and make InjectedType implement an interface, have TargetType inject that interface instead of injecting InjectedType directly, and then bind that interface to InjectedType. Otherwise, guice will have to do horrible stuff with bytecode rewriting on the fly and that's just asking for trouble.
I strongly urge you to look at your whole problem and refactor things so that you don't need to do this. Maybe your two objects don't need to know about each other in their constructors? For example, maybe you could pass them references to each other as method parameters by going through some supervisor object:
class TargetType {
#Inject
TargetType(#Assisted Param1 assistedParam)
{
}
void ttMethod1(InjectedType injected, String other) { }
// other methods
}
class InjectedType {
#Inject
injectedType(OtherInjectedType otherInjectedType)
{
}
void injMethod1(TargetType constructedTarget, String other) { }
// other methods
}
class TargetTypeSupervisor {
private TargetType target;
private InjectedType injected;
#Inject TargetTypeSupervisor(#Assisted Param1 assistedParam, InjectedType injected) {
this.injected = injected;
this.target = new Target(assistedParam);
}
void ttMethod1(String other) { target.ttMethod1(injected, other); }
void injMethod1(String other) { injected.injMethod1(target, other); }
// other methods as needed
}
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.
I have a command class that needs to have 2 constructors. However,
using structuremap it seems that I can only specify one constructor to
be used. I have solved the problem for now by subtyping the specific
command class, which each implementation implementing it's own
interface and constructor. Like the code below shows. The
ISelectCommand implements two separate interfaces for the
string constructor and the int constructor, just for the sake of
registering the two subtypes using structuremap.
However, I consider this a hack and I just wonder why is it not
possible for structuremap to resolve the constructor signature by the
type passed in as parameter for the constructor? Then I could register
the SelectProductCommand as an ISelectCommand and
instantiate it like:
ObjectFactury.With(10).Use>();
orObjectFactury.With("testproduct").Use>();
public class SelectProductCommand : ISelectCommand<IProduct>,
ICommand, IExecutable
{
private readonly Func<Product, Boolean> _selector;
private IEnumerable<IProduct> _resultList;
public SelectProductCommand(Func<Product, Boolean> selector)
{
_selector = selector;
}
public IEnumerable<IProduct> Result
{
get { return _resultList; }
}
public void Execute(GenFormDataContext context)
{
_resultList = GetProductRepository().Fetch(context,
_selector);
}
private Repository<IProduct, Product> GetProductRepository()
{
return ObjectFactory.GetInstance<Repository<IProduct,
Product>>();
}
}
public class SelectProductIntCommand: SelectProductCommand
{
public SelectProductIntCommand(Int32 id): base(x =>
x.ProductId == id) {}
}
public class SelectProductStringCommand: SelectProductCommand
{
public SelectProductStringCommand(String name): base(x =>
x.ProductName.Contains(name)) {}
}
P.s. I know how to tell structuremap what constructor map to use, but my again my question is if there is a way to have structuremap select the right constructor based on the parameter passed to the constructor (i.e. using regular method overloading).
The short answer is this post by the creator of Structuremap.
The long answer is regarding the structure you have in that piece of code. In my view, a command is by definition a "class" that does something to an "entity", i.e it modifies the class somehow. Think CreateNewProductCommand.
Here you are using commands for querying, if I'm not mistaken. You also have a bit of a separation of concern issue floating around here. The command posted defines what to do and how to do it, which is to much and you get that kind of Service location you're using in
private Repository<IProduct, Product> GetProductRepository()
{
return ObjectFactory.GetInstance<Repository<IProduct, Product>>();
}
The way I'd structure commands is to use CreateProductCommand as a data contract, i.e it only contains data such as product information.
Then you have a CreateProductCommandHandler which implements IHandles<CreateProductCommand> with a single method Handle or Execute. That way you get better separation of concern and testability.
As for the querying part, just use your repositores directly in your controller/presenter, alternatively use the Query Object pattern
I think I solved the problem using a small utility class. This class gets the concrete type from ObjectFactory and uses this type to construct the instance according to the parameters past into the factory method. Now on the 'client' side I use ObjectFactory to create an instance of CommandFactory. The implementation of CommandFactory is in another solution and thus the 'client solution' remains independent of the 'server' solution.
public class CommandFactory
{
public ICommand Create<T>()
{
return Create<T>(new object[] {});
}
public ICommand Create<T>(object arg1)
{
return Create<T>(new[] {arg1});
}
public ICommand Create<T>(object arg1, object arg2)
{
return Create<T>(new[] {arg1, arg2});
}
public ICommand Create<T>(object arg1, object arg2, object arg3)
{
return Create<T>(new[] {arg1, arg2, arg3});
}
public ICommand Create<T>(object[] arguments)
{
return (ICommand)Activator.CreateInstance(GetRegisteredType<T>(), arguments);
}
public static Type GetRegisteredType<T>()
{
return ObjectFactory.Model.DefaultTypeFor(typeof (T));
}
}
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 can do this in Castle Windsor:
public abstract class AbstractFactory
{
protected AbstractFactory(Foo constructorParm)
{
// Do something with parameter...
}
}
public class DescendentFactory : AbstractFactory
{
public DescendentFactory(Foo constructorParm) : base(constructorParm)
{
}
}
// The container is configured via XML, the service AbstractFactory and the
// type DescendentFactory
container.Resolve<AbstractFactory>("DescendentFactoryId", new { constructorParm = injectedValue });
Is this possible in Unity? I've tried doing it but it complains that it can't find the constructor. It seems I can only inject via the sub-type.
You can only inject via the sub-type. It needs a public constructor.
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).