What happened to constructor argument injection when getting instances of objects in StructureMap's ObjectFactory? - structuremap

Trying to upgrade/convert to StructureMap 3.0 from 2.6
I have code that manually set constructor arguments via the With method off of the ObjectFactory
ObjectFactory.With(ctorArgument).GetInstance<ClassThatHasACtorArgument>();
What is the StructureMap 3.0 equivalent now?

Doh... it was moved into the global container...
ObjectFactory.Container.With(ctorArgument).GetInstance<ClassThatHasACtorArgument>();

Related

C# SourceGenerators and Dependency Injection

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

Autofac DI, type not assignable to service

I simply cannot figure this out. Using Autofac with .Net core 2.0 and trying to resolve some simple dependencies. Feel like I've tried everything so my current code doesn't reflect everything I've tried.
Here is one of the exceptions I'm getting from Autofac
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'Elucidate.Core.Application.ValuesController' can be invoked with the available services and parameters: Cannot resolve parameter 'Elucidate.Core.Data.Repository.IRepository'1[Elucidate.Core.Model.User.IUser]rep' of constructor 'Void .ctor(Elucidate.Core.Data.Repository.IRepository`
Here is where I'm trying to get the dependency injected
public ValuesController(IRepository<IUser> rep)
Here is how I'm registering the types in an autofac module
builder.RegisterType<User>().As<IUser>();
builder.RegisterType<CoreUserStore<User>>();
builder.RegisterType(typeof(Repository<User>)).As<Repository<IUser>>();
builder.RegisterType<EntityFrameworkModelContext<User>>(); //.As<IModelContext>();
What am I doing wrong? I'm new to autofac, used to Unity which seems to be extinct.
The ValuesController constructor is expecting IRepository<IUser> and you haven't wired the correct type in Autofac.
You need to register the concrete repository type as the implemented interface, note the .As<IRepository...:
builder.RegisterType(typeof(Repository<User>)).As<IRepository<IUser>>();
Or alternatively "ask" for the concrete type in the constructor.
public ValuesController(Repository<IUser> rep)
The first is probably the preferred approach. You can also do:
builder.RegisterType<Repository<User>>().AsImplementedInterfaces();
Which will register the concrete type as all implemented interfaces.

How to specify constructor when registrating class in asp.net 5 with default Dependecy Injection

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.

Telling StructureMap to use another Constructor

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.

How can I use Ninject WCF extension with a singleton service?

I'm using Ninject 2.2.1.4 and Ninject.Extensions.Wcf 2.2.0.4.
My service is decorated with the following attribute:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
Using the above attribute, I receive the error:
"The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host."
If I remove the attribute Ninject works as expected.
After doing some research it's my understanding that since the service is marked as a singleton it will automatically be created with a parameter-less constructor by the ServiceHost, hence the error message. In order to resolve the issue, I have to create the service object myself, resolved using ninject, and then pass that singleton object off to the ServiceHost to use. I'm not sure how to do that.
I looked at the WCF extension source and I see that NinjectServiceHost inherits from ServiceHost, so my thought was to bind NinjectServiceHost to my instance of the service object using the overloaded constructor:
public NinjectServiceHost( object singletonInstance )
: base( singletonInstance )
{
}
I'm not sure if that's correct and if it is, how and where to properly bind it so the ServiceHost can be fed my instance.
Any suggestions? Thanks.
If you can live with a beta Version I suggest to update to 2.3.x It supports IIS hosted singleton Services. See also the examples on github

Resources