How do I setup Autofac such that it can pass a registered component as an argument to another component? - autofac

I have
builder.Register<ISomething>(c => new Something()).InstancePerLifetimeScope();
what would this look like in Autofac if Something took an argument that was an interface also resolved by Autofac?
builder.Register<ISomeInitializer>(c => new SomeInitializer()).InstancePerLifetimeScope();
builder.Register<ISomething>(c => new Something(????)).InstancePerLifetimeScope();

If you don't want to pass any special argument to your services then you can just write:
builder.Register<SomeInitializer>().As<ISomeInitializer>()
.InstancePerLifetimeScope();
builder.Register<Something>().As<ISomething>()
.InstancePerLifetimeScope();
In this case Autofac will instantiate your SomeInitializer with its default constructor and it will instantiate your Something with passing in the SomeInitializer.
In you want to keep your current code you can use the c parameter (which is an IComponentContext) to resolve your dependencies:
builder.Register<ISomeInitializer>(c => new SomeInitializer())
.InstancePerLifetimeScope();
builder.Register<ISomething>(c => new Something(c.Resolve<ISomeInitializer>()))
.InstancePerLifetimeScope();

Related

Automapper version 12 fails test on MapFrom when using ToLowerInvariant()

On Version 11 of automapper the below works fine but now that i upgraded to version 12 it fails. If i remove the ".ToLowerInvariant()" part then it passes the test.
Here is the mapping code:
CreateMap<UserEditProfileViewModel, ApplicationUser>(MemberList.Source)
.ForMember(dest => dest.Email, opts => opts.MapFrom(src => src.Email.ToLowerInvariant()))
.ForMember(dest => dest.UserName, opts => opts.MapFrom(src => src.Email.ToLowerInvariant()))
.ForSourceMember(src => src.Roles, opts => opts.DoNotValidate());
The error message is:
Test method TIP.Tests.TIP.Web.AutoMapperProfiles.AccountManagementProfileShould.BeValid threw exception:
AutoMapper.AutoMapperConfigurationException:
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
=======================================================================================================================
UserEditProfileViewModel -> ApplicationUser (Source member list)
TIP.Web.Features.AccountManagement.ViewModels.UserEditProfileViewModel -> TIP.Domain.Entities.Identity.ApplicationUser (Source member list)
Unmapped properties:
Email
Is it a bug or something has changed in version 12? How can i move forward?

LightInject - How to Register Multiple Interfaces to a Single Service?

How do I register a service that implements 4 interfaces?
For example: class Foo : IFoo, IBar, IApp, ISee { ... }
I was hoping for something like this:
container.Register<IFoo, IBar, IApp, ISee, Foo>();
But it appears this signature is for passing various types into a factory, in this case a factory that takes 4 parameters.
For those how also have this same question. Here is one possible way of solving it:
container.Register(_ => new Foo(), new PerScopeLifetime());
container.Register<IFoo>(factory => factory.GetInstance<Foo>());
container.Register<IBar>(factory => factory.GetInstance<Foo>());
container.Register<IApp>(factory => factory.GetInstance<Foo>());
container.Register<ISee>(factory => factory.GetInstance<Foo>());
In my specific case I also need to ensure that there was only one instance of Foo() within each scope. I.e. web request.

EF6 error when using in-memory testing

Mocked setup below (the GenerateTrades() and other methods in ContextFactory are just returning a List AsQueryable with sample data):
_trades = ContextFactory.GenerateTrades();
_hedges = ContextFactory.GenerateHedges();
_exposures = ContextFactory.GenerateExposures();
_ctx = new Mock<FxContext>();
var fakeTrades = new Mock<DbSet<Trade>>();
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.Provider).Returns(_trades.Provider);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.Expression).Returns(_trades.Expression);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.ElementType).Returns(_trades.ElementType);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.GetEnumerator()).Returns(_trades.GetEnumerator());
var fakeHedges = new Mock<DbSet<Hedge>>();
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.Provider).Returns(_hedges.Provider);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.Expression).Returns(_hedges.Expression);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.ElementType).Returns(_hedges.ElementType);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.GetEnumerator()).Returns(_hedges.GetEnumerator());
var fakeExposures = new Mock<DbSet<Exposure>>();
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.Provider).Returns(_exposures.Provider);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.Expression).Returns(_exposures.Expression);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.ElementType).Returns(_exposures.ElementType);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.GetEnumerator()).Returns(_exposures.GetEnumerator());
_ctx.Setup(c => c.Trades).Returns(fakeTrades.Object);
_ctx.Setup(c => c.Hedges).Returns(fakeHedges.Object);
_ctx.Setup(c => c.Exposures).Returns(fakeExposures.Object);
Part of test code looks like:
_sut = (from x in _ctx.Object.Hedges
where x.Id == ContextFactory.s_hedge01Id
select x).FirstOrDefault();
_ctx.Object.Hedges.Attach(_sut);
_ctx.Object.Entry(_sut).Collection(x => x.HedgedTrades).Load();
On the last line I get an exception:
{"Member 'Load' cannot be called for property 'HedgedTrades' because the entity of type 'Hedge' does not exist in the context. To add an entity to the context call the Add or Attach method of DbSet<Hedge>."}
I have verified that in fact the _sut Hedge is actually an instance of a Hedge (not null or a stub) and as the code seems to indicate, I have attached the Hedge to the context explicitly (though I would think the query should bring the object into the context automagically). Am I missing something?
It seems like here in your test you are mixing two separate approaches. Error you received states that you are trying to access DbContext inherited logic, but it is mocked. If you want to perform your unit tests against database with use of FxContext then do not mock it. If you want test other part of software then you should mock interface that FxContext should implement. This will enable you to fullfil dependency injection principle in your code which will help you then organize your test in more predictable way.

FubuMVC: How to configure which ISessionState implementation to use

I have some trouble making Fubu use my own implementation of ISessionState.
My controller has a constructor that takes an ISessionState argument.
I have tried using StructureMap like so in my global asax
FubuApplication.For<ConfigureFubu>().StructureMapObjectFactory(container =>
{
container.Scan(scanner =>
{
scanner.TheCallingAssembly();
scanner.WithDefaultConventions();
});
container
.For<ISessionState>()
.Use<MySessionState>();
})
.Bootstrap();
Where and how am I supposed to tell Fubu to use MySessionState instead of SimpleSessionState?
#Pingvinen This should work as is. What's happening, exactly? I'm assuming you're getting SimpleSessionState injected instead of your implementation?
Just for kicks, you may try going into your ConfigureFubu class and modifying the services (in the constructor):
Services(x => x.ReplaceService<ISessionState, MySessionState>());

Using Autofac to provide types exported by static factory

I have a dependency which provides a number of services using its static ServiceManager. It also provides a list of available types.
Type[] ServiceManager.GetServiceTypes();
object GetService(Type t);
In an Autofac Module, I'd like to enumerate these types and register 'dynamic instantiation' of them. It's important that I call ServiceManager.GetService each time an instance is requested.
I ended up using my own RegistrationBuilder, looks pretty funky but it works. Have I missed an obvious trick?
foreach (var type in ServiceManager.GetServiceTypes())
{
var rb = RegistrationBuilder.ForDelegate(
type,
(ctx, parms) => ServiceManager.GetService(type))
.ExternallyOwned();
builder.RegisterCallback(
cr => RegistrationBuilder.RegisterSingleComponent(cr, rb));
}