I have a tag helper with multiple constructors in my ASP.NET Core application. This causes the following error at runtime when ASP.NET 5 tries to resolve the type:
InvalidOperationException: Multiple constructors accepting all given argument types have been found in type 'MyNameSpace.MyTagHelper'. There should only be one applicable constructor.
One of the constructors is parameterless and the other has some arguments whose parameters are not registered types. I would like it to use the parameterless constructor.
Is there some way to get the ASP.NET 5 dependency injection framework to select a particular constructor? Usually this is done through the use of an attribute but I can't find anything.
My use case is that I'm trying to create a single class that is both a TagHelper, as well as a HTML helper which is totally possible if this problem is solved.
Apply the ActivatorUtilitiesConstructorAttribute to the constructor that you want to be used by DI:
[ActivatorUtilitiesConstructor]
public MyClass(ICustomDependency d)
{
}
This requires using the ActivatorUtilities class to create your MyClass. As of .NET Core 3.1 the Microsoft dependency injection framework internally uses ActivatorUtilities; in older versions you need to manually use it:
services.AddScoped(sp => ActivatorUtilities.CreateInstance<MyClass>(sp));
Illya is right: the built-in resolver doesn't support types exposing multiple constructors... but nothing prevents you from registering a delegate to support this scenario:
services.AddScoped<IService>(provider => {
var dependency = provider.GetRequiredService<IDependency>();
// You can select the constructor you want here.
return new Service(dependency, "my string parameter");
});
Note: support for multiple constructors was added in later versions, as indicated in the other answers. Now, the DI stack will happily choose the constructor with the most parameters it can resolve. For instance, if you have 2 constructors - one with 3 parameters pointing to services and another one with 4 - it will prefer the one with 4 parameters.
ASP.NET Core 1.0 Answer
The other answers are still true for parameter-less constructors i.e. if you have a class with a parameter-less constructor and a constructor with arguments, the exception in the question will be thrown.
If you have two constructors with arguments, the behaviour is to use the first matching constructor where the parameters are known. You can look at the source code for the ConstructorMatcher class for details here.
ASP.NET Core Answer
I've ended up with the following workaround until they fix/improve this.
First, declare only one constructor in your controller (passing your required configuration settings only), considering that the settings objects passed in the constructor can be null (.NET Core will inject them automatically if you configure them in the Startup method):
public class MyController : Controller
{
public IDependencyService Service { get; set; }
public MyController(IOptions<MySettings> settings)
{
if (settings!= null && settings.Value != null)
{
Service = new DependencyServiceImpl(settings.Value);
}
}
}
Then, in your tests methods you can instantiate the controller in two ways:
Mocking the IOptions object when you construct the tested object
Construct passing null in all parameters and then Stub the dependency that you will use in your tests. Following you have an example:
[TestClass]
public class MyControllerTests
{
Service.Controllers.MyController controller;
Mock<IDependencyService> _serviceStub;
[TestInitialize]
public void Initialize()
{
_serviceStub = new Mock<IDependencyService>();
controller = new Service.Controllers.MyController(null);
controller.Service = _serviceStub.Object;
}
}
From this point you can have full testing with dependency injection and mocking ready in .NET Core.
Hope it helps
Azure Functions .NET 7 Isolated
Building on Kévin Chalet answer, if you're using azure functions issolated, you can call the GetService function.
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices(s => {
s.AddHttpClient();
s.AddSingleton<DataLookup>(l => {
var dependency = l.GetService<IHttpClientFactory>();
return new DataLookup(dependency);
});
})
.Build();
Related
I've developed a CQRS style database access framework based on Tripod and other inspirations but targeting .NET Standard and simplifying for easier use. I want to split the IoC into separate integration packages so consumers can get the type registration I'm currently doing internally easily without being locked into a specific IoC container. My issue is I've only really worked closely with SimpleInjector so not familiar with other systems and their nuances around how they handle specific scenarios. I have an iminent need to support Autofac so thought I'd try here to see if anyone can translate.
I have the following Simple Injector CompositionRoot static class:
public static void RegisterDatabase(this Container container, DbContextOptions<EntityDbContext> dbContextOptions, params Assembly[] assemblies)
{
var scopedLifeStyle = container.Options.DefaultScopedLifestyle;
//container.Register<ICreateDbModel, DefaultDbModelCreator>(scopedLifeStyle); // lifestyle c
container.RegisterInitializer<EntityDbContext>( //(container.InjectProperties);
handlerToInitialise => handlerToInitialise.ModelCreator = new DefaultDbModelCreator()
);
// Setup DbContext
var ctxReg = scopedLifeStyle.CreateRegistration(
() => new EntityDbContext(dbContextOptions),
container);
container.AddRegistration<IUnitOfWork>(ctxReg);
container.AddRegistration<IReadEntities>(ctxReg);
container.AddRegistration<IWriteEntities>(ctxReg);
}
In ASP.NET Core solutions I invoke the above from Startup.Configure(...) with:
var optionsBuilder = new DbContextOptionsBuilder<EntityDbContext>()
//.UseInMemoryDatabase("Snoogans");
.UseSqlServer(_config.GetConnectionString("DefaultConnection"));
container.RegisterDatabase(optionsBuilder.Options);
which allows me to switch out to an in memory database for unit testing if needed. EntityDbContext contains all my unit of work methods for calling onto the context without having to specify explicit DbSet for each table. The IUnitOfWork, IReadEntities and IWriteEntities interfaces all define methods on the EntityDbContext.
So I'm not sure how I'd go about making an Autofac module that allows scoped registration of the dbcontext with passed in DbContextOptions followed by multiple registrations of interfaces to this registration.
Does anyone know how this can be achieved?
I worked out the process and now have an AutoFac module. I was able to registermodule by instance of the class and also pass in the options when I instantiate. Because EntityDbContext implements the three interfaces I was registering separately in the Simple Injector scenario, AutoFac has the convenience of being able to just infer them and register with AsImplementedInterfaces()
public class EntityFrameworkModule : Module
{
private readonly DbContextOptions<EntityDbContext> _dbContextOptions;
public EntityFrameworkModule(DbContextOptions<EntityDbContext> dbContextOptions)
{
_dbContextOptions = dbContextOptions;
}
protected override void Load(ContainerBuilder builder)
{
// If the calling code hasn't already registered a custom
// ICreateDbModel then register the internal DefaultDbModelCreator
builder.RegisterType<DefaultDbModelCreator>()
.IfNotRegistered(typeof(ICreateDbModel))
.As<ICreateDbModel>();
// Expecting IUnitOfWork, IReadEntities and IWriteEntities to be registered with this call
builder.Register(c => new EntityDbContext(_dbContextOptions)
{
ModelCreator = c.Resolve<ICreateDbModel>()
})
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
}
}
I'm trying to implement the Identity system in an ASP.NET Core app (RC2 libraries) and there is a particular hangup that is driving me crazy.
First of all, I am not using EntityFramework. I'm not even using SQL. I'm backing up to RavenDB, so I need the implementation to be very specific to that; Which isn't a problem.
So I designed a RavenUserStore class, and it looks like this;
public class RavenUserStore<TUser> :
IUserStore<TUser>,
IUserLoginStore<TUser>,
IUserPasswordStore<TUser>,
IUserRoleStore<TUser>,
IUserSecurityStampStore<TUser>,
IUserClaimStore<TUser>,
IUserLockoutStore<TUser>,
IUserTwoFactorStore<TUser>,
IUserEmailStore<TUser> {
// ...
}
Works great on its own. I've implemented all the methods, etc. It's wonderful. Very clean and efficient.
Now, I go over to my web application and wire things up;
services.AddTransient<ILookupNormalizer>(s => new LowerInvariantLookupNormalizer());
services.AddTransient<IPasswordHasher<Member>>(s => new PasswordHasher<Member>());
services.AddTransient<IUserStore<Member>, RavenUserStore<Member>>();
services.AddIdentity<Member, Role>(o => {
o.Password.RequiredLength = 6;
o.Password.RequireDigit = true;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
})
.AddUserStore<RavenUserStore<Member>>()
.AddRoleStore<RavenRoleStore<Role>>();
So I go make a controller to use this, per all the samples I've seen, and the very core sample from the Identity Framework Github Repository
//... [PROPERTIES]...//
public AccountController(UserManager<Member> userManager, SignInManager<Member> signInManager) {
// ... [attach constructor parameters to properties] ...//
}
Alright, so I inspect the classes carefully.
UserManager<T> has a property Store,which is a type of IUserStore<T>.
So theoretically.. if the dependency injection resolves types of IUserStore<T> to RavenUserStore<T> when they are injected through a constructor.. shouldn't that mean that the UserManager<T> gets a RavenUserStore<T> as its Store property?
I thought it would too; But when I call methods on the UserManager, it DOES NOT call the ones on my RavenUserStore. Why is this? What can I do?
Do I really have to ALSO make a custom UserManager class and do all of those methods AGAIN?
You need to add your own custom providers before calling services.AddIdentity(). Internally, AddIdentity uses TryAddScoped() which only adds the default items if they don't already exist in the services container.
So just putting the call to AddIdentity() after you registered all your custom implementations should mean that they will take precedence as you expect.
I got a method able to create a CSV file thanks to StreamedResponse object of Symfony2 framework. I use the method several times so I put a callback parameter to personalise the behavior (I forget the buzz word for this practice in Object-Oriented Programming).
Where is the best place to put this method in a MVC project?
Repository? (Model/DAO/Manager)
Entity? (POPO)
Controller
Service
Through a interface (This object able to create CSV file)
Other
As your logic returns a response, the most adapted context is a controller.
Also, if your logic is called from multiple contexts or by multiple classes of the same context (e.g. controllers), to avoid duplicated code, you have two possibilities (at least) :
1 - Use an AbstractController and make your controllers extends the abstract.
2- Use a service (i.e. CsvManager).
If you want some example implementations, see Symfony2 reusable functions in controllers and the Controller as a service chapter of the Symfony documentation.
An example of service implementation:
// src/AppBundle/Services/CsvManager.php
class CsvManager
{
public function generate(/** params */)
{
// Return your streamed response
}
}
The service declaration :
// app/config/services.yml
services:
# ...
app.csv_manager:
class: AppBundle\Services\CsvManager
Now, you can use the service from all your controllers and other contexts that implements the services container. example:
// src/AppBundle/Controller/TestController.php;
class TestController extends \Symfony\Bundle\FrameworkBundle\Controller\Controller
{
public function printCsvAction()
{
$csvManager = $this->get('app.csv_manager');
return $csvManager->generate(/** params */);
}
}
All of my SignalRHubs have their own service interface, this is used on the client side for type safe calling; ie no more referring to methods by string.
Anyways with this setup I have had to add a HubName attribute to all my hubs with the Interface name. Is it even possible to have the hubs resolved by these interfaces.
I did try replacing the resolver both in GlobalHost and in the HubConfiguration object with a Ninject resolver but it didn't seem to ever call the resolved for the hubs themselves.
Here is an example of a hub:
[HubName("IFoobarService")]
public class FoobarHub : Hub, IFoobarService
{
public void Baz(BazDto dto)
{
Clients.Others.Baz(dto);
}
}
}
Here is the code I used to try to bind my hubs with Ninject
kernel.Bind(x => x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom()
.BindAllInterfaces());
I think that using the HubName attribute is your best bet.
You could provide your own IHubDescriptorProvider and register it with SignalR's DependencyResolver, but I wouldn't recommend it.
You can take a look at the default IHubDescriptorProvider implemenation here: https://github.com/SignalR/SignalR/blob/2.0.2/src/Microsoft.AspNet.SignalR.Core/Hubs/Lookup/ReflectedHubDescriptorProvider.cs#L56
Notice the following line of code:
var hubDescriptors = types
.Select(type => new HubDescriptor
{
NameSpecified = (type.GetHubAttributeName() != null),
Name = type.GetHubName(),
HubType = type
});
Type.GetHubName() is implemented as an extension method here:
https://github.com/SignalR/SignalR/blob/2.0.2/src/Microsoft.AspNet.SignalR.Core/Hubs/Extensions/HubTypeExtensions.cs#L9
You could replace the ReflectedHubDescriptorProvider with your own IHubDescriptorProvider implementation that calls into your own GetHubName method, but I think that would be overkill.
Once again, I think using the HubName attribute is your best bet.
I want to implement IOC in my application but i am confused, in my application i have multiple concrete classes which implement an interface. Consider this scenario:-
I have an Inteface ICommand and following concrete types which implement this interface:-
AddAddress
AddContact
RemoveAddress
RemoveContact
Basically user performs all this action in UI and then List is passed to the service layer where each command is executed.
So in GUI layer I will write
ICommand command1 = new AddAddress();
ICommand command2 = new RemoveContact();
In command manger
List<ICommand> listOfCommands = List<ICommand>();
listOfCommands.Add(command1);
listOfCommands.Add(command2);
Then finally will pass listOfCommands to service layer.
Now as per my understanding of IOC is only one concrete class is mapped to the interface. And we use this syntax to get our concrete type from StructureMap container.
ICommand command = ObjectFactory.GetInstance<ICommand>();
How should i implement IOC in this scenario?
In this scenario you're better off making your commands into value objects, i.e. not created by the IoC container:
class AddAddressCommand {
public AddAddressCommand(string address) {
Address = address;
}
public string Address { get; private set; }
}
When you create a command, you really do want a specific implementation, and you want to parameterise it precisely, both concerns that will work against the services of the IoC container. This will become even more relevant if you decide at some point to serialize the command objects.
Instead, make the service-layer components that execute the commands into IoC-provided components:
class AddAddressHandler : IHandler<AddAddressCommand> {
public AddAddressHandler(ISomeDependency someDependency) { ... }
public void Handle(AddAddressCommand command) {
// Execution logic using dependencies goes here
}
}
In your case, the component that accepts the list of commands to execute will need to resolve the appropriate handler for each command and dispatch the command object to it.
There's some discussion of how to do this with Windsor here: http://devlicious.com/blogs/krzysztof_kozmic/archive/2010/03/11/advanced-castle-windsor-generic-typed-factories-auto-release-and-more.aspx - the community supporting your IoC container of choice will be able to help you with its configuration.
As mentioned by Mark, StructureMap will allow you to set up and call named instances of an interface:
ObjectFactory.Initialize(x =>
{
x.For<ISomeInterface>().Add<SomeImplementation>().Named("SomeName");
}
You can still add a default instance for that particular interface, of course:
ObjectFactory.Initialize(x =>
{
x.For<ISomeInterface>().Add<DefaultImplementation>();
x.For<ISomeInterface>().Add<SomeImplementation>().Named("SomeName");
}
When you call ObjectFactory.GetInstance<ISomeInterface>(); the default instance (the one initialized with Use instead of Add) is the one that will be returned.
So in your case, the set up would look something like:
ObjectFactory.Initialize(x =>
{
// names are arbitrary
x.For<ICommand>().Add<AddAddress>().Named("AddAddress");
x.For<ICommand>().Add<RemoveContact>().Named("RemoveContact");
}
These would be called as pointed out by Mark:
ObjectFactory.GetNamedInstance<ICommand>("AddAddress");
ObjectFactory.GetNamedInstance<ICommand>("RemoveContact");
Hope this helps.
Most IOC containers allow you to register "named instances" of interfaces, allowing you to register several implementations of ICommand, each with its own unique name. In StructureMap, you request them like this:
ObjectFactory.GetNamedInstance<ICommand>("AddAddress");
Have a look at this question to see how you setup the container in StructureMap.