SimpleIoc (mvvmlight) - how to automatically register all classes implementing a particular interface - mvvm-light

Using SimpleIoc I want to automatically register all classes that implement a particular interface. I couldn't see a method on SimpleIoc's container to do this automatically so I put a some code together to iterate through the types to be registered. Unfortunately the code's not happy (see the commented line).
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(typeof(IFoo).IsAssignableFrom);
foreach (var type in types.Where(x=>x.IsClass))
{
container.Register<IFoo, type>(); //this line won't compile as type can't be resolved by the compiler
}
I realise there are less elegant ways of registering classes (such as just hard coding "container.Register" to register each class to the interface) but I'd like to be able to add new implementations without having to keep updating the ioc installer code. It would also be useful, at some point, for me to be able to register classes in other assemblies using the same method.
Any idea what I have to change to make this build (or is there a simpler/more elegant way to do this)?
UPDATE fex posted this comment:
"you can always iterate over types (like you do in your question) and create it with reflection (in your factory class) - (IFoo)Activator.CreateInstance(type); - in fact that's how service locators / ioc containers do it internally (in simplify)."
I've now updated my code to the following which works, with one caveat (the implementations must have a parameterless constructor, and dependencies must therefore be satisfied by the factory that I'm then using to serve up instances implementing IFoo). I've included the factory registration too for info.
Updated code:
// Get the types that implement IFoo...
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(typeof(IFoo).IsAssignableFrom);
// Register these types and use reflection to instantiate each instance...
foreach (var type in types.Where(x=>x.IsClass))
{
var t = type;
container.Register(() => (IFoo)Activator.CreateInstance(t), t.ToString());
}
// Inject all registered instances of IFoo into IFooFactory when it's instantiated.
// Note that instances of IFoo must have their own dependencies satisfied via the
// factory at runtime before being served by the factory.
container.Register<IFooFactory>(
() => new FooFactory(container.GetAllInstances<IFoo>()));

Related

Differences between different methods of Symfony service collection

For those of you that are familiar with the building of the Symfony container, do you know what is the differences (if any) between
Tagged service Collector using a Compiler pass
Tagged service Collector using the supported shortcut
Service Locator especially, one that collects services by tags
Specifically, I am wondering about whether these methods differ on making these collected services available sooner or later in the container build process. Also I am wondering about the ‘laziness’ of any of them.
It can certainly be confusing when trying to understand the differences. Keep in mind that the latter two approaches are fairly new. The documentation has not quite caught up. You might actually consider making a new project and doing some experimenting.
Approach 1 is basically an "old school" style. You have:
class MyCollector {
private $handlers = [];
public function addHandler(MyHandler $hamdler) {
$handlers[] = $handler;
# compiler pass
$myCollectorDefinition->addMethodCall('addHandler', [new Reference($handlerServiceId)]);
So basically the container will instantiate MyCollector then explicitly call addHandler for each handler service. In doing so, the handler services will be instantiated unless you do some proxy stuff. So no lazy creation.
The second approach provides a somewhat similar capability but uses an iterable object instead of a plain php array:
class MyCollection {
public function __construct(iterable $handlers)
# services.yaml
App\MyCollection:
arguments:
- !tagged_iterator my.handler
One nice thing about this approach is that the iterable actually ends up connecting to the container via closures and will only instantiate individual handlers when they are actually accessed. So lazy handler creation. Also, there are some variations on how you can specify the key.
I might point out that typically you auto-tag your individual handlers with:
# services.yaml
services:
_instanceof:
App\MyHandlerInterface:
tags: ['my.handler']
So no compiler pass needed.
The third approach is basically the same as the second except that handler services can be accessed individually by an index. This is useful when you need one out of all the possible services. And of course the service selected is only created when you ask for it.
class MyCollection {
public function __construct(ServiceLocator $locator) {
$this->locator = $locator;
}
public function doSomething($handlerKey) {
/** #var MyHandlerInterface $handler */
$handler = $serviceLocator->get($handlerKey);
# services.yaml
App\MyCollection:
arguments: [!tagged_locator { tag: 'app.handler', index_by: 'key' }]
I should point out that in all these cases, the code does not actually know the class of your handler service. Hence the var comment to keep the IDE happy.
There is another approach which I like in which you make your own ServiceLocator and then specify the type of object being located. No need for a var comment. Something like:
class MyHandlerLocator extends ServiceLocator
{
public function get($id) : MyHandlerInterface
{
return parent::get($id);
}
}
The only way I have been able to get this approach to work is a compiler pass. I won't post the code here as it is somewhat outside the scope of the question. But in exchange for a few lines of pass code you get a nice clean custom locator which can also pick up handlers from other bundles.

What is the proper way to inject (via constructor) different types that implement that same interface?

For example, let's say I have an interface 'IFeed' and two concrete types ('Feed1' and 'Feed2') that implement this interface. Now let's say I have a 'FeedManager' type that takes multiple parameters that will get resolved dynamically, two of which are of type 'IFeed' and I'd like both concrete type to be injected via constructor injection, not via manual resolve (I only use resolve once at the composition root). I have a feeling that I should be using a factory but I wanted to see what the proper way of doing this might be. Many thanks in advance.
If you want ALL implementations of IFeed, you can use array syntax in your constructor and then nothing special is needed at type registration time.
container.RegisterType<IFeedManager, FeedManager>();
container.RegisterType<IFeed, FeedA>("FeedA"); // The name doesn't matter
container.RegisterType<IFeed, FeedB>("FeedB"); // The name doesn't matter
Then the manager constructor...
public FeedManager(IFeed[] feeds) {...}
or if you want to add a little flare for calling the constructor directly...
public FeedManager(params IFeed[] feeds) {...}
Assuming you want to determine the actual concrete instances at runtime, you need to use named type registrations and then tell unity which one you want. So, use a factory method to construct the types required and pass those in as parameter overrides. Unity will use the overrides and resolve any remaining dependencies.
// register the types using named registrations
container.RegisterType<IFeedManager,FeedManager>()
container.RegisterType<IFeed, Feed1>("Feed1")
container.RegisterType<IFeed, Feed2>("Feed2")
Assuming your feed manager has the following named constructor parameters
class FeedManager : IFeedManager
{
public FeedManager (IFeed Feed1, IFeed Feed2, string someOtherDependency)
{
}
}
and create your feed manager:
static IFeedManager CreateFeedManager()
{
ParameterOverride feed1 = new ParameterOverride("Feed1"
,_container.Resolve<IFeed>("feed1"));
ParameterOverride feed2 = new DependencyOverride("Feed2"
,_container.Resolve<IFeed>("feed2"));
IFeedManager = _container.Resolve<IFeedManager>(feed1,feed2)
return IFeedManager;
}
Obviously this is overly simplified, but you you insert your own logic to determine which instance is to be resolved and then injected for each of the IFeed instances required by the FeedManager.
With Unity you would do this like so:
container.RegisterType<IFeed, Feed1>("Feed1");
container.RegisterType<IFeed, Feed2>("Feed2");
container.RegisterType<FeedManager>(new InjectionConstructor(new ResolvedParameter<IFeed>("Feed1"),
new ResolvedParameter<IFeed>("Feed2")));
This has now configured Unity so that when it needs to resolve a FeedManager, it will resolve Feed1 for the first parameter and Feed2 for the second parameter.

can I use Moq to grab values that are passed into a public method of an object that is not a mock?

I'm writing a unit test for FluentMigrator. I am testing a method that gets called n times in succession. What I'd like to do is grab the successive inputs and stow them in a SortedList, so that I can verify the methods were called in the right order, then pass those inputs to the actual method -- like a temporary redirect. But, after reading the docs etc, I can't get it to work.
Code in the test:
var listOfVersions = new SortedList<int, long>();
int i = 0;
var runnerMock = Mock.Get(_runner); // runner is a MigrationRunner
runnerMock.Setup(r => r.RollbackToVersion(2))
.Callback((long v) =>
{
listOfVersions.Add(i, v);
i++;
_runner.RollbackToVersion(v, true); });
_runner.RollbackToVersion(2);
The error:
System.ArgumentException : Object instance was not created by Moq.
Parameter name: mocked
I'm coming from Moles, where dipping into the behavior of an object and then redirecting it isn't unusual. Maybe it is in Moq?
No. Really mocking frameworks fall into 2 camps. The ones that can mock anything and the other than can only mock Interfaces, Abstract/Virtual methods.
This is because they use very much a different interception technology. Moq, RhinoMocks etc use Castle's Dynamic Proxy Generator under the hood which all it does create an instance that exposes the same public interface. It uses this to record interactions with that object so you can verify on it. Abstract and Virtual members can be mocked cause it can derive from that class and prevent calls to the base class.
However Moles and TypeMock Isloator play around with the IL directly. I know for TypeMock it actually weaves IL into the methods you are trying to mock so you can intercept and record interactions on it for testing (It also stops further processing of the methods also). I know that Moles creates another assembly and you refer to that in your test method but I imagine it does very similar things to TypeMock.
If you want to mock concrete non overrideable methods you will have to use that latter frameworks.

Unity and constructors

Is it possible to make unity try all defined constructors starting with the one with most arguments down to the least specific one (the default constructor)?
Edit
What I mean:
foreach (var constructor in concrete.GetConstructorsOrderByParameterCount())
{
if(CanFulfilDependencies(constructor))
{
UseConstructor(constructor);
break;
}
}
I don't want Unity to only try the constructor with most parameters. I want it to continue trying until it finds a suitable constructor. If Unity doesn't provide this behavior by default, is it possible to create an extension or something to be able to do this?
Edit 2
I got a class with two constructors:
public class MyConcrete : ISomeInterface
{
public MyConcrete (IDepend1 dep, IDepend2 dep2)
{}
public MyConcrete(IDepend1 dep)
{}
}
The class exists in a library which is used by multiple projects. In this project I want to use second constructor. But Unity stops since it can't fulfill the dependencies by the first constructor. And I do not want to change the class since the first constructor is used by DI in other projects.
Hence the need for Unity to try resolving all constructors.
Unity will choose the constructor with the most parameters unless you explicitly tag a constructor with the [InjectionConstructor] attribute which would then define the constructor for Unity to use.
When you state a suitable constructor; that is somewhat contingent on the environment. If for instance you always want to guarantee that a certain constructor is used when making use of Unity use the attribute mentioned previously, otherwise explicitly call the constructor you want to use.
What would be the point of Unity "trying" all constructors? It's purpose is to provide an instance of a type in a decoupled manner. Why would it iterate through the constructors if any constructor will create an instance of the type?
EDIT:
You could allow the constructor with the most params to be used within the project that does not have a reference to that type within its container by making use of a child container. This will not force the use of the constructor with a single param but it will allow the constructor with 2 params to work across the projects now.
You could also switch to using the single constructor across the board and force the other interface in via another form of DI (Property Injection), not Constructor Injection...therefore the base is applicable across the projects which would make more sense.

how can i use structure map asp.net 3.5

I am new to the structure map but i want to use it in my asp.net site for dependency injection
can any one suggest me simple example to use structure map for the dependency injection
you will need to do something like this:-
StructureMapConfiguration
.ForRequestedType<IResourceA>()
.TheDefaultIsConcreteType<ResourceB>()
.CacheBy(InstanceScope.Singleton);
This tells StructureMap to inject ResourceB when there is a request for ResourceA.
Structure Map
You can configure programatically or via configuration file.
Programatical example (there are other ways):
StructureMap.StructureMapConfiguration.ForRequestedType<ISomething>().TheDefaultIsConcreteType<ConcreteSomething>();
then you can get an instance of the configured type using this sort of code:
//The concrete type will be ConcreteSomething
ISomething instance = ObjectFactory.GetInstance<ISomething>();
You can do it in a config file:
<StructureMap MementoStyle="Attribute">
<DefaultInstance PluginType="Blah.ISomething, Blah.SomethingDLL" PluggedType="Blah.Concrete.ConcreteSomething,Blah.ConcreteDLL"/>
</StructureMap>
and in the main method or Global.asax you can set this config by saying:
StructureMap.ObjectFactory.Initialize(x => { x.PullConfigurationFromAppConfig = true; });
and use it the same way as above:
ISomething instance = ObjectFactory.GetInstance<ISomething>();
If the concrete class has a constructor that needs instances injected in it, and you have those configured, the concrete types will get injected by the framework.
There are ways of passing parameters to constructors, dealing with Gereric types, creating named instances that are configured with specific constructor/property values. I use this framework and like it very much.

Resources