ninject factory constructor selection with runtime generics - constructor

How can I use a ninject factory, which creates an instance with constructor parameters, without relying on the argument names.
The problem is that the ToConstructor()-Method not works, because I bind it to a generic definition.
The following example works, if I use the factory method with the corresponding constructor argument name, but I don't like it rely on names.
Because the following solution is very fragil and breaks if someone chooses a wrong name or renames the ctor-argument in the derived class.
Any solution?
Here's the example code:
[TestFixture]
public class NinjectFactoryBindingsTest
{
[Test]
public void ConstructorSelectionWithArguments()
{
NinjectSettings ninjectSettings = new NinjectSettings();
ninjectSettings.LoadExtensions = false;
using (var kernel = new StandardKernel(ninjectSettings, new FuncModule()))
{
// IDependencyA will be passed to the factory, therefore it is not bounded
//kernel.Bind<IDependencyA>().To<DependencyA>();
kernel.Bind<IDependencyB>().To<DependencyB>();
kernel.Bind(typeof(IGenericBaseClass<>)).To(typeof(GenericDerivedClass<>));
kernel.Bind<IGenericClassFactory>().ToFactory();
IGenericClassFactory factory = kernel.Get<IGenericClassFactory>();
DependencyA dependencyA = new DependencyA();
IGenericBaseClass<GenericImpl> shouldWorkInstance = factory.Create<GenericImpl>(dependencyA);
Assert.NotNull(shouldWorkInstance);
}
}
}
public interface IGenericClassFactory
{
IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA someName) where TGeneric : IGeneric;
// This works, but relies on ctor-param-names!!!
// IGenericBaseClass<TGeneric> Create<TGeneric>(IDependencyA otherNameThanInBaseClass) where TGeneric : IGeneric;
}
public class DependencyA : IDependencyA
{
}
public class DependencyB : IDependencyB
{
}
public class GenericDerivedClass<TGeneric> : GenericBaseClass<TGeneric> where TGeneric : IGeneric
{
public GenericDerivedClass(IDependencyA otherNameThanInBaseClass, IDependencyB dependencyB)
: base(otherNameThanInBaseClass, dependencyB)
{
}
}
public abstract class GenericBaseClass<TGeneric> : IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
protected GenericBaseClass(IDependencyA dependencyA, IDependencyB dependencyB)
{
}
}
public interface IGenericBaseClass<TGeneric> where TGeneric : IGeneric
{
}
public interface IDependencyB
{
}
public interface IDependencyA
{
}
public class GenericImpl : IGeneric
{
}
public interface IGeneric
{
}

The factory extension has the convention that arguments must have the same name as the constructor argument they will be passed to. There are no easy ways to do it differently. The only way I can think of is about the following:
Create a new IParameter implementation that can hold a reference to an IDependencyA.
Create either a hardcoded factory or a custom IInstanceProvider (see documentation) that creates an instance of your IParameter implementation so that it is passed to the Get<> request
Add a new binding for IDependencyA: Bind<IDependency>().ToMethod(ctx => extract and return your parameter from the context)

Related

Castle Windsor: get informed by the container after any object was resolved

I'm using Castle Windsor as DI Container and have following question:
Is it possible to get informed by the container each time, any object was created by the container and get a reference to this object?
I want to check after each resolve, if the resolved object implements a special interface (e.g. IEmergencyStop). I want to register this object at a special service (EmergencyStopHelper).
Following an example:
interface IEmergencyStop
{
void Stop();
}
interface IMotor : IEmergencyStop
{
void Run();
}
class Motor : IMotor
{
}
class EmergencyStopHelper
{
List<IEmergencyStop> emergencyStopList = new List<IEmergencyStop>();
public void Register(IEmergencyStop aClass)
{
emergencyStopList.Add(aClass);
}
public void StopAll() => emergencyStopList.ForEach( x => x.Stop());
}
container.Register(Component.For<IMotor>().ImplementedBy<Motor>().LifestlyleTransient());
container.Register(Component.For<EmergencyStopHelper>());
// TODO: any magic code which calls EmergencyStopHelper.Register(...)
// after following resolve
IMotor aMotor = container.Resolve<IMotor>();
var emergencyStop = container.Resolve<EmergencyStopHelper>();
emergencyStop.StopAll();

mvvmcross - multiple Init methods in viewmodel with different signature not working

in a main viewmodel where i collect data from another viewmodels, I created in summary two or three public Init methods with different signatures. When i navigate back to the base viewmodel from the other viewmodels with ShowViewModel, I awaited that the right Init method will be executed, but this don't happen. Regarding the greet practical documentation here:
http://slodge.blogspot.ch/2013/03/v3-new-viewmodel-lifecycle.html
This should be work :-/.
I will explain this with some code.
My main view model is e.g.:
public class MainViewModel : MvxViewModel
{
MainViewModel() {}
public class ParameterFirst
{
public string Id { get; set; }
}
public class ParameterSecond
{
public string Id { get; set; }
}
public class ParameterSecond
{
public string Id { get; set; }
}
public class ParameterThird
{
public string Id { get; set; }
}
public void Init(ParameterFirst objFirst)
{
//do something
}
public void Init(ParameterSecond objSecond)
{
//do something
}
public void Init(ParameterThird objThird)
{
//do something
}
}
Then I will navigate from another viewmodel and await that the right Init method will be executed:
public class CollectData_ONE_ViewModel : MvxViewModel
{
CollectData_ONE_ViewModel() {}
public void DidWork()
{
//Hopefully the Init method with argument ParameterFirst should be called
base.ShowViewModel<MainViewModel>(new MainViewModel.ParameterFirst { Id = "11" });
}
}
next here the second viewmodel
public class CollectData_SECOND_ViewModel : MvxViewModel
{
CollectData_SECOND_ViewModel() {}
public void DidWork()
{
//Hopefully the Init method with argument ParameterFirst should be called
base.ShowViewModel<MainViewModel>(new MainViewModel.ParameterSecond { Id = "22" });
}
}
and the third viewmodel
public class CollectData_THIRD_ViewModel : MvxViewModel
{
CollectData_THIRD_ViewModel() {}
public void DidWork()
{
//Hopefully the Init method with argument ParameterFirst should be called
base.ShowViewModel<MainViewModel>(new MainViewModel.ParameterThird { Id = "33" });
}
}
In my code, each time the First Init method is called, I'm really at the end and don't have further ideas :) Did anyone here experienced the same issue? Or do anyone here have another Idea to collect data to the main viewmodel in an elegant way? Thanks a lot in advance for reading :)
The Init mechanism in MvvmCross is deliberately lightweight. If you declare multiple methods, all of them will be called - this is by design. Also if some of the Init parameter objects were to share properties then these would clash - see Custom types in Navigation parameters in v3
As it says in the blog post you reference "generally you will probably only want to use one within your application" - so I'd recommend refactoring to a single navigation parameter object and using your own ViewModel-based logic to decide how your ViewModel should initialise.
If you really do need three Init methods called in three different situations, then you can easily pack and unpack your own parameter objects using a custom method (possibly in a BaseViewModel class) like in https://stackoverflow.com/a/19059938/373321

registering open generic decorators for typed implementations in castle windsor

While trying to coerce Windsor into wrapping an implementation with a random number of decorators, i've stumbled upon the following:
i have 3 decorators and an implementation all using the same interface.
if you run this code, windsor resolves icommandhandler<stringcommand> as implementation, which, as far as i can tell, is expected behaviour, because the typed implementation can not be registered with the open typed decorators.
However, if you uncomment the line container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());, all three decorators will be used to resolve implementation, which is the desired result (sort of : ).
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator1<>)));
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator2<>)));
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator3<>)));
//uncomment the line below and watch the magic happen
//container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());
container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<implementation>());
var stringCommandHandler = container.Resolve<ICommandHandler<stringCommand>>();
var command = new stringCommand();
stringCommandHandler.Handle(command);
Console.WriteLine(command.s);
Console.ReadKey();
}
}
public interface ICommandHandler<T>
{
void Handle(T t);
}
public class stringCommand
{
public string s { get; set; }
}
public abstract class Decorator<T> : ICommandHandler<T>
{
public abstract void Handle(T t);
};
public class Decorator1<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator1(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator1;";
_handler.Handle(t);
}
}
public class Decorator2<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator2(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator2;";
_handler.Handle(t);
}
}
public class Decorator3<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator3(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator3;";
_handler.Handle(t);
}
}
public class implementation : ICommandHandler<stringCommand>
{
public void Handle(stringCommand t)
{
t.s += "implementation;";
}
}
Why exactly is this happening, is this a feature of windsor that i am not aware of? Is there perhaps a different way to achieve the same effect? (without resorting to reflection)
When windsor tries to resolve a component it will first try to resolve the more specific interface. So when you register Component.For it will prefer to resolve this over an open generic type.
If the same interface is registered multiple times, it will use the first one specified.
So if you don't uncommment the line your application will resolve implementation since this is the most specific component.
If you do uncomment the line decorator1 will be resolved and indeed the magic starts. The decorator will now start looking for the first registered component that satisfies it's constructor, in this case that would be decorator1 again (you did notice that your output show decorator1 2 times ?). Which will the resolve the next registered component and so on till it comes to the actual implementation.
So the only thing I can think about is not registering decorator1 as an open generic but as a specific type.
Kind regards,
Marwijn.

castle windsor register a generic interface and retrieve all registered instances the inherit indirectly from it

I have the following structure -
public interface IBaseInterface<T>
{
}
public interface IChildInterface1<Class1> : IBaseInterface<Class1>
{
}
public interface IChildInterface2<Class2> : IBaseInterface<Class2>
{
}
public class ImplementationClass1 : IChildInterface1<Class1>
{
}
public class ImplementationClass2 : IChildInterface2<Class2>
{
}
I want to register all types in the assembly that implement IBaseInterface directly or indirectly, so I want to be able to register ImplementationClass1 and ImplementationClass2 given IBaseInterface. And then I want to retrieve any concrete type based on the generic type definition of ChildInterface classes.
I am registering types like this -
container.Register(
AllTypes.FromAssemblyContaining<Class1>()
.BasedOn(typeof(IBaseInterface<>))
.WithService.Base()
.Configure(c => c.LifeStyle.Transient)
);
and then resolving the type using
var impl = container.Resolve(typeof(IChildInterface1<>))
I expected this to give me an instance of ImplementationClass1, however I get the error -
No component for supporting the service IChildInterface`1 was found
Can someone figure out what I am doing wrong, is this even a valid scenario that I am attempting?
This is my whole code -
using Castle.MicroKernel.Registration;
namespace complexresolutionioc
{
class Program
{
static void Main(string[] args)
{
var container = new Castle.Windsor.WindsorContainer();
container.Register(
AllTypes.FromAssemblyContaining<Class1>()
.BasedOn(typeof(IBaseInterface<>))
.WithService.AllInterfaces()
.Configure(c => c.LifeStyle.Transient)
);
var thisWorks = container.Resolve<IChildInterface1<Class2>>();
}
}
public interface IBaseInterface<T>
{
}
public interface IChildInterface1<Class1> : IBaseInterface<Class1>
{
}
public interface IChildInterface2<Class2> : IBaseInterface<Class2>
{
}
public class ImplementationClass1 : IChildInterface1<Class1>
{
}
public class ImplementationClass2 : IChildInterface2<Class2>
{
}
public class Class1 { }
public class Class2 { }
}
gives me this error -
No component for supporting the service complexresolutionioc.IChildInterface1`1[[complexresolutionioc.Class2, complexresolutionioc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] was found
at Castle.MicroKernel.DefaultKernel.Resolve(Type service) in c:\TeamCity\buildAgent\work\1ab5e0b25b145b19\src\Castle.Windsor\MicroKernel\DefaultKernel_Resolve.cs:line 172
at Castle.Windsor.WindsorContainer.Resolve(Type service) in c:\TeamCity\buildAgent\work\1ab5e0b25b145b19\src\Castle.Windsor\Windsor\WindsorContainer.cs:line 889
at Castle.Windsor.WindsorContainer.ResolveT in c:\TeamCity\buildAgent\work\1ab5e0b25b145b19\src\Castle.Windsor\Windsor\WindsorContainer.cs:line 978
at complexresolutionioc.Program.Main(String[] args) in C:\MyDev\complexresolutionioc\complexresolutionioc\Program.cs:line 21
-ilias
You need to provide closed generic type you want to resolve:
var thisWorks = container.Resolve<IChildInterface1<Class2>>();

Can you implement an interface on a Linq2Sql class?

I have an interface called IAddress, and a class called Address that handles street, city, state/province, postal code and country. I have a couple of Linq2Sql classes that has all the address information and would like to implement the interface IAddress, and pass that in to the constructor for Address that would the load the property values.
Is it possible have a Linq2Sql class impment and interface through the partial class that I created for it? Thanks in advance!
Additional comments
In my class I have a property called MailToStreet, I want that to map to IAddress.Street. Is there a way to do this in the partial class?
Solved
Thanks StackOverflow community! It was a snap! Here is my final code:
public partial class Location : IAddress
{
string IAddress.Street
{
get { return this.Street; }
set { this.Street = value; }
}
string IAddress.City
{
get { return this.City; }
set { this.City = value; }
}
string IAddress.StateProvince
{
get { return this.StateProvince; }
set { this.StateProvince = value; }
}
string IAddress.PostalCode
{
get { return this.PostalCode; }
set { this.PostalCode = value; }
}
string IAddress.Country
{
get { return this.Country; }
set { this.Country = value; }
}
}
LinqToSQL classes are partial classes, so you can have an additional file that implements the interface for the LinqToSQL class.
Just add this to a new file, using the same class name as your LinqToSQL class:
public partial class LinqToSqlClass : IFoo {
public void Foo() {
// implementation
}
}
If your LinqToSQL class already implements the necessary proporties you should be able to only include the interface declaration.
To answer the comment about using a differently-named LinqToSQL property to implement the interface, you can use the syntax above and just call the LinqToSQL property from the interface property, or to keep things a bit cleaner, use explicit implementation:
public partial class LinqToSqlClass : IFoo {
void IFoo.Foo() {
return this.LinqFoo(); // assumes LinqFoo is in the linq to sql mapping
}
}
By using this syntax, clients accessing your class will not see a redundant property used only for implementing an interface (it will be invisible unless the object is cast to that interface)