4

Is it possible to inject a type into a constructor instead of an instance? If so how is this achieved? I want to avoid explicitly registering a factory method or resolving an instance in situ if possible.

public interface IJob { }
public class TheJob : IJob { }

public interface IService
{
    string GetTypeDesc();
}

public class Service : IService
{
    private Type _jobType;

    public Service(Type jobType)
    {
        _jobType = jobType;
    }

    public string GetTypeDesc()
    {
        return _jobType.ToString();
    }
}

It seems even when registering the type with explicit constructor definition, Unity wants to inject an instance into the type place holder.

Type jobType = typeof(TheJob);    
(new UnityContainer()).RegisterType<IService, Service>(new InjectionConstructor(jobType));

2 Answers 2

1

The constructor of InjectionConstructor takes an array of objects. If the type of an object passed to the constructor of InjectionConstructor (in the array) is of type Type, unity will try to resolve that type and then pass the result into the constructor (of 'Service` for example).

For example, if you use new InjectionConstructor(typeof(IMyOtherService)), then unity will expect that the constructor of Service takes an instance of type IMyOtherService and will use the container to resolve such type. In other words Type is a special case that you need to handle in a specific way.

To solve your issue, you should tell Unity that the Type you are passing is actually a constructor parameter. You can do this like this:

new InjectionConstructor(new InjectionParameter(jobType))

This forces unity to treat jobType as a constructor parameter.

For more details see the InjectionParameterValue.ToParameter method here: https://github.com/unitycontainer/unity/blob/master/source/Src/Unity-CoreClr/Injection/InjectionParameterValue.cs

Sign up to request clarification or add additional context in comments.

4 Comments

If I do this with RegisterType<,> I get an error: The type UnitySample.Service does not have a constructor that takes the parameters (RuntimeType). I'm starting to think this is not possible without some wrapper or intermediate factory which is a shame.
Sorry my bad! I had a problem in my original code. Please ignore. Is there any way to make the job registration simpler? I used to register like this in main() container.RegisterType<IJob, TheSpecificJob>(). So keep the InjectionConstructor common, but hookup different IJob implementations?
@user183872, can you provide a complete (minimal) example? If it is different from the current question, I suggest you create another one.
you're right. I have several windows services which use common scheduling code which doesn't reference the underlying service. I kind of like just wiring a job instance to a type in the main() rather than specifying the more complex InjectionConstruction each time. Probably splitting hairs;)
1

Is it possible to inject a type into a constructor instead of an instance?

A System.Type is an ambiguous type, just like primitive types such as System.String and System.Int32. They are considered ambiguous, because at runtime there are multiple (or many) possible values of the type. This prevents a DI Container from automatically resolving and injecting an instance of such value for you.

This means that you should manually supply the value to Unity. This can be done using the InjectionConstructor (as you are already doing):

.RegisterType<IService, Service>(new InjectionConstructor(jobType))

Or using a InjectionFactory:

.Register<IService>(new InjectionFactory(c => new Service(jobType)))

2 Comments

The above causes a Unity exception though (The type UnitySample.Service does not have a constructor that takes the parameters (TheJob).)
@user183872: should work. Read this article for information about it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.