简体   繁体   中英

Simple Injector: Registering open generic type with constructor parameter

I have created a generic type

public interface IContext<T> {}

And, I have a type implemented that (with a constructor with parameters)

public class Context<T> : IContext<T> { public Context(string url, string key) { } ... }

I want to register with simple injector. With the below code, I dont know how to pass the values for the constructor

container.Register(typeof(IContext<>), typeof(Context<>))

This one shows a way if I have a type passed in the constructor parameter. However, for me its primitive types only. Looks like by overriding construction resolution behaviour I may achieve this. But, dont really get the idea of how shall I leverage it. Can someone guide me to find an appropriate way to register this?

When dealing with primitive dependencies into an open-generic registration, the typical solution is to extract the set of configuration value(s) into a DTO and inject that DTO into the type's constructor; this allows you to register that new configuration object as singleton into the container:

I have created a generic type

public interface IContext {}

And, I have a type implemented that (with a constructor with parameters)

public class ContextConfiguration
{
    public readonly string Url;
    public readonly string Key;
    public ContextConfiguration(string url, string key) { ... }
}

public class Context<T> : IContext<T>
{
    public Context(ContextConfiguration config)
    {
    }
    ...
}

// Configuration
container.RegisterSingleton(new ContextConfiguration(...));
container.Register(typeof(IContext<>), typeof(Context<>));

In case you can't change the constructor of that type, you create a sub class of that type that you place inside the Composition Root . This sub type again uses this configuration DTO:

// Part of the Composition Root
private class ContextConfiguration
{
    public readonly string Url;
    public readonly string Key;
    public ContextConfiguration(string url, string key) { ... }
}

private class CompositionRootContext<T> : Context<T>
{
    public Context(ContextConfiguration config) : base(config.Url, config.Key)
    {
    }
    ...
}

// Configuration
container.RegisterSingleton(new ContextConfiguration(...));
container.Register(typeof(IContext<>), typeof(CompositionRootContext<>));

If that Context<T> is sealed, you could override the parameter injection behavior , but in general, in that case you are dealing with a type that is defined by an external library. For external types it is generally better to hide them behind an application-tailored abstraction (according to the DIP ). Instead of letting application code depend on IContext<T> , you let the application depend on an interface that is defined by the application. As part of your Composition Root, you would implement an Adapter that adapts the application-specific interface to Context<T> . The constructor of that adapter would -again- be able to use this configuration DTO.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM