We have hit an issue where we would like to inject a dependency into an object that has been constructed via reflection:
Type _type = Type.GetType(className, true, true);
ConstructorInfo _ctor = _type.GetConstructor(new[] { typeof(MyClass) });
IReg _reg = (IReg)_ctor.Invoke(new object[] { _myClass });
The injection does not seem to be happening here using property injection. Is it not possible? How can we get around this issue?
Thanks.
You can do property inject on the object after it's construction via reflection with the kernel.Inject(Object) method on IKernel. But this WILL be post construction and you will not get any constructor injection.
There's a Kernel.Get(Type), but as you want to call a specific constructor, it's no use. There is a constructor selection strategy which is customizable, which you could use to emulate what you're doing in your second line.
To use the dependency injection framework you shouldn't instantiate object by itself using new or reflection you should call the injection framework.
In your case:
//setup the application
IKernel kernel = new StandardKernel();
//add all your other bindings for property injection
...
kernel.Bind<MyClass>.ToConstant(_myClass); //if same _myClass instance is used than this can go in setup application.
Type _type = Type.GetType(className, true, true);
var _reg = kernel.Get(_type);
kernel.Unbind<MyClass>(); //cleanup the global kernel
Any way the dependency injection framework is used to avoid using reflection for object instantiation + wiring it's dependencies, based on previously configuration (using Bind calls for Ninject).
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 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();
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.
The ValidationManager has a public Dictionary for storing UI components that implement the IValidatable interface.
I am testing a command class that needs an instance of ValidationManager and I want it to fail the validations. So I override the ValidationManager's "validateItem()" method like so:
var validationManagerRepos:ValidationManager = ValidationManager(mockRepository.createStub(ValidationManager));
var validationItem:IValidatable = IValidatable(mockRepository.createStub(IValidatable));
var validatableItems:Dictionary = new Dictionary();
validatableItems[validationItem] = false;
SetupResult.forCall(validationManagerRepos.validateItem(validationItem)).returnValue(false);
My problem is in the execute method of the command. It checks to see if the validationItem is both a DisplayObject (isVisble) and IValidatable. Any slick way to stub a typed object AND an interface? Or do I just need to create an instance of some existing object that already satisfies both?
for (var iVal:Object in validationManager.validatableItems)
{
if (isVisible(DisplayObject(iVal)))
{
passed = validationManager.validateItem(IValidatable(iVal));
eventDispatcher.dispatchEvent(new ValidationEvent(ValidationEvent.VALIDATE_COMPLETED, IValidatable(iVal), passed));
if (!passed)
{
allPassed = false;
}
}
}
I'm fairly sure you can't do both within asMock. It's a limitation of the Flash Player because of lack of polymorphism.
I believe what you'll have to do is create a testing object that does both (extend DisplayObject and implement IValidatable) and create a mock object of that.
The concept of a "multimock" is certainly possible, but floxy (the framework that asmock uses to generate dynamic proxies) doesn't support it. I previously considered adding support for it, but it would be difficult to expose via the various Mock metadata and there's be other issues to worry about (like method name clashes).
I agree with J_A_X's recommendation of creating a custom class and then mocking that.