Autofac: How do I register generic collections? - autofac

I have a couple of classes that take IList<IHero> in the constructor. I would like to register the generic collection List<IHero> in Autofac so that whenever Autofac needs to resolve a service that takes IList<IHero, it returns a new instance of List<IHero>. The code below compiles but I get a ton of error messages at run-time.
builder.RegisterType<List<IHero>>().As<IList<IHero>>();
My current workaround is as follows:
var printer = scope.Reseolve<IPrinter>(new TypedParameter(typeof(IList<IHero>), new List<IHero>();
var newEngine = scope.Resolve<IEngine>(new TypedParameter(typeof(IPrinter), printer));

Don't register collections yourself. Autofac handles collections for you.

Related

how init a val out the object in scala?

A redis cluster client should should be shared in many place,am I right? with the google, so I use a RedisCli object:
object RedisCli {
val jedisClusterNodes = new java.util.HashSet[HostAndPort]()
jedisClusterNodes.add(new HostAndPort("192.168.1.100", 6379))
lazy val jedisCluster = new JedisCluster(jedisClusterNodes)
//...method with jedisCluster
}
the problem is how can I init the jedisCluster out the object--I want init the HostAndPort in the main method of other object, get the ip from properties file the file passed by command line. should I just use class RedisCli in my circumstance?
I think I am totally lost in class and object.
In Scala all members of a singleton objects should be defined. While you are allowed to modify var members from the outside, take a step back and ask yourself what is the point of having a singleton object in your case if each client can modify its members? You will only end up with spaghetti code.
I would highly recommend using a dependency injection framework (Spring for example) where you can create beans in a specific place then inject them where you need them.
In a nutshell singleton objects should be used when you want to define methods and values (never seen a case where a var is used) that are not specific to each instance of a class (think Java static). In your case, you seem to want different instances (otherwise why should they be set from client code) but want a certain instance to be shared across different clients and this is exactly what dependency injection allows you to do.
If you don't want to use a DI framework and are okay with having clients modify your instances as they please, then simply use a class as opposed to an object. When you use the class keyword, different instances can be instantiated.
class RedisCli(val ip: String, val port: Int) {
val hostAndPort: HostAndPort = new HostAndPort(ip, port)
etc...
}
Hope this helps.

How to call constructor with interface arguments when mocking a concrete class with Moq

I have the following class, which uses constructor injection:
public class Service : IService
{
public Service(IRepository repository, IProvider provider) { ... }
}
For most methods in this class, I simply create Moq mocks for IRepository and IProvider and construct the Service. However, there is one method in the class that calls several other methods in the same class. For testing this method, instead of testing all those methods together, I want to test that the method calls those methods correctly and processes their return values correctly.
The best way to do this is to mock Service. I've mocked concrete classes with Moq before without issue. I've even mocked concrete classes that require constructor arguments with Moq without issue. However, this is the first time I've needed to pass mocked arguments into the constructor for a mocked object. Naturally, I tried to do it this way:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
However, that does not work. Instead, I get the following error:
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: My.Namespace.Service.
Could not find a constructor that would match given arguments:
Castle.Proxies.IRepository
Castle.Proxies.IProvider
This works fine if Service's constructor takes simple arguments like ints and strings, but not if it takes interfaces that I'm mocking. How do you do this?
Why are you mocking the service you are testing? If you are wishing to test the implementation of the Service class (whether that be calls to mocked objects or not), all you need are mocks for the two interfaces, not the test class.
Instead of:
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Mock<Service>(repository.Object, provider.Object);
Shouldn't it be this instead?
var repository = new Mock<IRepository>();
var provider = new Mock<IProvider>();
var service = new Service(repository.Object, provider.Object);
I realize that it is possible to mock concrete objects in some frameworks, but what is your intended purpose? The idea behind mocking something is to remove the actual implementation so that it does not influence your test. But in your question, you have stated that you wish to know that certain classes are called on properly, and then you wish to validate the results of those actions. That is undoubtedly testing the implementation, and for that reason, I am having a hard time seeing the goals of mocking the concrete object.
I had a very similar problem when my equivalent of Service had an internal constructor, so it was not visible to Moq.
I added
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
to my AssemblyInfo.cs file for the implementing project. Not sure if it is relevant, but I wanted to add a suggestion on the off chance that it helps you or someone else.
It must be old version issue, all is ok with latest version. Nick, Please check!
P.s.: I started bounty by misstake (I had wrong signature in my constructor).

Is there any way to create a fake from a System.Type object in FakeItEasy?

Is there any way to create a fake from a System.Type object in FakeItEasy? Similar to:
var instance = A.Fake(type);
I try to write a fake container for AutoFac that automatically return fakes for all resolved types. I have looked in the code for FakeItEasy and all methods that support this is behind internal classes but I have found the interface IFakeObjectContainer that looks pretty interesting, but the implementations still need registration of objects that is the thing that I want to come around.
As of FakeItEasy 2.1.0 (but do consider upgrading to the latest release for more features and better bugfixes), you can create a fake from a Type like so:
using FakeItEasy.Sdk;
…
object fake = Create.Fake(type);
If you must use an earlier release, you could use some reflection based approach to create a method info for the A.Fake() method. (since it's about auto mocking this shouldn't be a problem really).
This is best done using a registration handler. You should look into how AutofacContrib.Moq implements its MoqRegistrationHandler. You'll see that it is actually using the generic method MockRepository.Create to make fake instances. Creating a similar handler for FakeItEasy should be quite simple.

Registering Collections in Autofac 2.1.10 RC

I am upgrading code from Autofac 1.4 to 2.1.10 Release Candidate.
My module previously performed registration like this:
builder.RegisterCollection<IExceptionHandler>()
.As<IEnumerable<IExceptionHandler>>()
.FactoryScoped();
builder.Register<AspNetExceptionHandler>()
.As<IExceptionHandler>()
.MemberOf<IEnumerable<IExceptionHandler>>()
.FactoryScoped();
Now, RegisterCollection has no parameterless overload. I don't care about assigning it a name. Assuming it's OK to just pass in null, my code looks like this in 2.1:
builder.RegisterCollection<IExceptionHandler>(null)
.As<IEnumerable<IExceptionHandler>>()
.InstancePerDependency();
builder.RegisterType<AspNetExceptionHandler>()
.As<IExceptionHandler>()
.MemberOf<IEnumerable<IExceptionHandler>>(null)
.InstancePerDependency();
However, when I compile, I get the following error regarding .MemberOf:
Using the generic method
'Autofac.RegistrationExtensions.MemberOf(Autofac.Builder.RegistrationBuilder,
string)' requires '3' type arguments
I tried putting in a collection name instead of null, just in case, and that had no effect.
What's the proper way to register collections in 2.1?
As I understand it, you just register a bunch of IExceptionHandler types, and then when you request an IEnumerable<IExceptionHandler> Autofac 2 will just take care of everything for you.
From the NewInV2 page:
builder.RegisterType<A1>().As<IA>();
builder.RegisterType<A2>().As<IA>();
var container = builder.Build();
// Contains an instance of both A1 and A2
Assert.AreEqual(2, container.Resolve<IEnumerable<IA>>().Count());

How to carry out custom initialisation with autofac

I'm adding autofac to an existing project and some of the service implementations require their Initialize method to be called and passed configuration information. Currently I'm using the code:
builder.Register(context =>
{
var service =
new SqlTaxRateProvider(context.Resolve<IUserProvider>());
service.Initialize(config);
return service;
}
).As<ITaxService>()
.SingleInstance();
which works but I'm still creating the object myself which is what I'm trying to get away from this and allow autofac to handle it for me. Is it possible to configure a post create operation that would carry out the custom initialisation?
To give you an idea of what I'm after ideally this would be the code:
builder.RegisterType<SqlTaxRateProvider>()
.As<ITaxService>()
.OnCreated(service=> service.Initialize(config))
.SingleInstance();
Update:
I am using Autofac-2.1.10.754-NET35
.OnActivating(e => e.Instance.Initialize(...))
should do the trick.
You might also investigate the Startable module (see the Startable entry in the Autofac wiki).
Mark's suggestion to do initialisation in the constructor is also a good one. In that case use
.WithParameter(new NamedParameter("config", config))
to merge the config parameter in with the other constructor dependencies.