Playing with the new .NET 5 ISourceGenerators.
From what I understand, the class that implements ISourceGenerator must have a zero-parameter contructor.
Are there any plans to allow constructor DI?
Right now I am instantiating a ServiceCollection and ServiceProvider instance in a default instance constructor.
closing this out... i have accepted that DI is not the way to go...for now
Related
This question already has answers here:
Dependency injection, inject with parameters
(5 answers)
Closed 1 year ago.
I want to inject IServiceProvider (and possibly some other services) into a service and/or a custom class whose constructor takes OTHER non-injectable parameters.
Here is an example of what my service/class would look like:
public class MyService {
IServiceProvider _sProvider;
/*possibly other injectable services*/
public MyService(object someCustomStuff, IServiceProvider sProvider) {
// --- keep reference for later use in methods...
_sProvider = sProvider;
}
}
Note that if I am able to access IServiceProvider, I can then retrieve any service I need on the fly using _sProvider.GetService(typeof(MyRequiredService)) so I don't necessarily have to inject other services here.
Still, my requirement is to somehow use injection here.
For a service registered in Startup.ConfigureServices. The default services.AddSingleton<MyService>() throws an error as the injection is not able to retrieve the first someCustomStuff parameter as a service (and I don't want it to be one!). I actually tried the alternative way to register the service using the constructor explicitely :
services.AddSingleton(new MyService(myCustomStuff, _?IServiceProvider?_));
but I don't know how to access IServiceProvider in Startup.ConfigureServices explicitely...
This naturally leads to a more general question about constructor injection for non-component classes and in other places than Startup.ConfigureServices:
Is it possible (if so HOW) to get dependency injection with mixed constructors having both injected services and non-injectable parameters?
Is it possible (if so HOW) to use dependency injection via constructor in code where I do NOT have explicit access to the services to be injected (if I do, as for e.g. in components, it is trivial as I can easly inject the required services to the component and then forward them to the constructor explicitely...)
For part 1, the answer is to use the provided delegate approach:
services.AddSingleton<MyService>(provider => new MyService(myCustomStuff, provider));
To pass other injected dependencies in the constructor, get them from the provider (make sure the service is already registered, of course):
services.AddSingleton<MyService>(
provider =>
new MyService(myCustomStuff, provider.GetService<MyOtherService>())
);
Credits to this post
If I have a class HelperClass that I'd like to use within a saga, I'd like to be able to inject an IHelperClass into the constructor.
The problem I'm running into is that sagas appear to be instantiated with an empty constructor; so while I can create a constructor that takes IHelperClass and use it in unit tests, the framework will always call the parameterless constructor.
I think I could use property injection, but since this helper class is "necessary," my understanding is that property injection (assuming it would work) is not a best practice.
So how can I do this without taking a hard dependency on the concrete HelperClass implementation?
You don't have to worry about the "necessity" of the help object in the context of the saga since no other code will be instantiating the saga directly.
In short, you can use property injection without concern here.
Is there are possibility to instantiate class using ASP.NET 5 default Dependency Injection when that class have constructor with parameters?
I would like to register Repository with constructor that accepts connection_string.
UPDATE
I think that I can rephrase the question. I would like to specify which constructor will be called when the class is being registered. Something similar that Autofac have. Is that possible?
builder.RegisterType<ConfigReader>()
.As<IConfigReader>()
.WithParameter("configSectionName", "sectionName");
Unfortunately, the out of the box DI container does not support parameter constraints. It is all or nothing.
If you want advanced features, you can switch to another DI container, like Autofac, that you already mentioned and that is supported in ASP.NET 5.
I am currently converting a project that uses ServiceStack's DI to Unity. I am currently stuck at ServiceStack's RegisterAutoWired method that registers a concrete class.
container.RegisterAutoWired<MyClass>().ReusedWithin(ReuseScope.Request);
What method in IUnityContainer should I use to achieve the same result?
Just use IUnityContainer.RegisterType<MyClass, MyClass>();
You actually don't need to register concrete classes. Unity will new up a concrete class for you (but it defaults to picking the constructor with the most parameters). If you need to specify a specific constructor or if you need to set up a special lifetime, then you may want to register it.
unityContainer.RegisterType<MyClass>(
new ContainerControlledLifetimeManager(), // Singleton
new InjectionConstructor(myConstructorParameter1, ...);
Or if you have a complex scenario where you need to control how the type is instantiated, you can use RegisterInstance or an InjectionFactory.
var myClassInstance = new MyClass();
unityContainer.RegisterInstance(myClassInstance);
unityContainer.RegisterType<MyClass>(
new InjectionFactory(c => new MyClass()));
The Developer's Guide to Dependency Injection Using Unity is very helpful.
I have a class with 2 constructors.
MyClass()
and
MyClass(IMyService service)
How do I tell StructureMap then whenever I do a 'new MyClass()' it should actually call the second constructor and not the first constructor.
Please help.
If you call new MyClass(), then StructureMap is not involved at all. No amount of StructureMap configuration will change the behavior.
If you call ObjectFactory.GetInstance<MyClass>(), StructureMap will by default call the constructor with more parameters.
If you want StructureMap to use a different constructor, you can specify the constructor (via PHeiberg's answer):
x.SelectConstructor<IMyClass>(() => new MyClass(null));
Or you can just tell StructureMap explicitly how to create the instance using the overload of Use() that accepts a Func<>:
x.For<IMyClass>().Use(ctx => new MyClass(ctx.GetInstance<IMyService>()))
Joshua's answer is covering all aspects. As a side note in order to configure Structuremap to choose a specific constructor without hardcoding the arguments to the constructor as done in Joshua's example you can use the SelectContructor method:
x.SelectConstructor<MyService>(() => new MyService());
The lambda in the SelectConstructor method call should invoke the needed constructor (put nulls or any value of the correct type for all parameters present). See the documentation for further info.
When using a DI container like structuremap it's best to have just a single constructor on every class. This constructor has to resolve all the dependencies of the class, if IMyService is a dependency (which looks a bit strange though) this should always be resolved when instantiating so the parameterless constructor is not needed.