Telling StructureMap to use another Constructor - dependency-injection

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.

Related

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 do I perform constructor injection with an NServiceBus saga?

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.

Can one use a parameterized constructor with DbSet.Create(Type)?

I have a base class and a few different subclasses set up to instantiate as change-tracking proxies, and I’d like to use the DbSet.Create(Type) method to create additional proxies to add to my Model.
My application was developed before Code First became available, so before, when I created these objects, I’d use a parameterized constructor to initialize both the object and its base member variables and properties.
Will Entity Framework allow me to create a change-tracking proxy using a constructor containing a parameter list? Would I be able to pass some of these parameters to the base class (proxy) as well? (I’d like to stick with the Object Oriented paradigm if I can because it’ll make the code easier to maintain.) If you can show me how to use parameterized constructors to do this, I’d be grateful.
Thanks,
EF cannot use parametrized constructors. You must always provide parameterless constructor (but it doesn't have to be public).

StructureMap Constructor arguments

I'm new to structureMap. How do I define constructor arguments for the following class with fluent configuration? Thanks
public BlobContainer(CloudStorageAccount account
, string containerName
, string contentType
, BlobContainerPermissions blobContainerPermissions)
{
}
For primitive types you would go about as #ozczecho answered:
For<BlobContainer>()
.Use<BlobContainer>()
.Ctor<string>("containerName").Is("theContainerName")
.Ctor<string>("contentType").Is("theContentType");
provided that the values are known at registration time. You can do it this way for non-primitive types as well, but you lose the flexibility that the container gives you this way. It's better to define a default or named instance and use that instead (the container will automatically resolve default instances for you). By defining defaults you can easily change all the dependencies on a type in your application by changing just one registation.
For<CloudStorageAccount>().Use<TheCloudStorageAccountType>();
If a dependency is a concrete type with a constructor having dependencies that are known to structuremap you don't have to register it with the container, it will be automatically resolved.
So if CloudStorageAccount is a concrete class you only need to register it's dependencies in Structure Map.
For<BlobContainer>()
.HybridHttpOrThreadLocalScoped()
.Use<BlobContainer>()
.Ctor<CloudStorageAccount >("account").Is(...)
.Ctor<string >("containerName").Is(...)
.Ctor<string >("contentType").Is(...)
.Ctor<BlobContainerPermissions >("blobContainerPermissions").Is(...);

How to set a default constructor argument to null with StructureMap?

A class has a unique constructor taking IMyInterface as its argument. If I define a concrete type of IMyInterface and registers it to StructureMap then there is no issue and my class can be instanciated with this concrete type.
However, in some cases, no concrete type will be registered. In that case, I would like to receive null for the IMyInterface parameter. Instead I get an exception:
StructureMap Exception Code: 202
No Default Instance defined for PluginFamily IMyInterface.
Is it possible to define a default value for a missing plugin?
Context: my class, which is a service, uses the Spark view engine and defines some default namespaces. The service uses a ISparkNamespacesProvider (IMyInterface) to add aditional namespaces. The client app may register such a provider or not. That's why the constructor of the service will receive either a provider or none.
Taken from here:
For<IService>().Use<MyService>()
.Ctor<IMyInterface>("nameOfParameter").Is(null);
But You should think about why Your class is dependent on IMyInterface. If it's optional - that's a code smell. Maybe You should refactor it out as method argument for method that needs it or as settable property.
There shouldn't be need for switching between concrete implementation and null. When composing dependency graph at composition root, You should know exactly what will be Your dependencies w/o .If(isSomething()).Use<MyService>().Ctor<IMyInterface>(null).
You might want to check out this tekpub presentation and this book (look for so called MEAP access) about DI and IOC.
One way to accomplish what You want is using so called 'poor man dependency injection'. That is - to define second constructor:
public MyClass():this(null){...}
But I wouldn't recommend that.
StructureMap now supports this case via UseIfNone https://structuremap.github.io/registration/fallback-services/

Resources