Dependency injection (ninject) using strings, anti-pattern?

I have code that uses ninject to inject dependencies, these dependencies are actual strings. Is this an anti-pattern for entering strings, and not for creating a new object, for example.

those. I would like to enter Username and Password, would it be better to create a small class called credentials with 2 Usernamd and Password properties and insert this?

Entering strings into constructors can be done using

kernel.Bind<IUser>().To<User>() .WithConstructorArgument(@"username", configuration.Username) .WithConstructorArgument(@"password", configuration.Password); 

Is this code a smell?

Any ideas or improvements regarding what I'm doing?

+8
c # dependency-injection ninject
source share
5 answers

I would prefer to use ToMethod() here:

 kernel.Bind<IUser>() .ToMethod(ctx => new User(configuration.Username, configuration.Password)); 

If the User constructor has other dependencies, I would defer @ jgauffin's answer.

You can still use ToMethod() with Kernel :

 kernel.Bind<IUser>() .ToMethod(ctx => new User(configuration.Username, configuration.Password, ctx.Kernel.Get<Foo>())); 
+5
source share

Is this code a smell?

Yes. Either create a ConfigurationRepository , or create a factory / builder (two different design patterns) that creates different services and then register that factory / builder in the container.

I have a problem with this code too:

 kernel.Bind<IUser>().To<User>() .WithConstructorArgument(@"username", configuration.Username) .WithConstructorArgument(@"password", configuration.Password); 

The IoC container is not initially used to create domain objects, but to create services / repositories / controllers, etc., i.e. to create objects that control the flow in your application.

+2
source share

I try to avoid primitive type injections.

After looking at the code you posted, my first instinct will be to create an "IConfigurationService" and add it if necessary. This service will contain properties for username and password.

0
source share

There seem to be two questions here:

  • Is it a smell code / anti primitive input pattern?
  • Should there be some type to create usernames and passwords?

These are completely different problems. First, addiction is addiction. This may be complex or primitive, but dependency management must be consistent. If you use an IoC container, this is absolutely not a code smell for entering primitives. The IoC container and root composition are preferred parts of code that understands the needs of all services and how to satisfy them. Conceptually, this is done for complex and primitive types. In practice, however, there are various mechanisms for registering complex dependencies against primitive dependencies. The approach with the name of the argument you specified is fully valid. Other approaches depend on the index of the argument. The choice between them is to split the hairs, but it comes down to whether you want freedom to rename the constructor arguments or give the constructor arguments without changing the connection code.

An alternative is the presence of specific dependencies (or, even worse, the Locator pattern), which is a slippery slope towards an illegible ball of dirt.

Secondly, whether to combine two strings into a type depends on how often these values ​​are used together and how DRY you want to be. At some point, a decrease in drying efficiency is observed. In addition, if values ​​are always entered together, you can simply reformulate the Ninject configuration calls. No matter what you choose, make sure the rationale matches the code base.

The last point that uses IoC containers to manage objects is considered code smell. Entities are usually responsible for maintaining domain invariants when performing domain actions. (Not sure if the context / intent of the example code snippet cannot provide an alternative.)

0
source share

Consider a build dedicated to storing all of your injection interfaces. In my current working solution (prism using MEF), I have a class that declares constant strings for your use.

Why are you using constants over literals? Because it is a symbol; it is refactored, detected, and the actual contents of the string do not matter. I always use the GUID as a suffix in my lines so that I can "guarantee" uniqueness. A constant is also available for use in attribute decorations.

 /// <summary> /// Exposes top level application region names for use when registering views. /// </summary> public static class Regions { public const string WORKSPACE_REGION = "WorkspaceRegion {4CCDA460-D1A8-4BCE-863A-593021079F02}"; //names include a GUID to prevent clashes. public const string TOOL_DIAGRAM_REGION = "ToolDiagramRegigon {AD3CED71-C49D-4BD8-86FF-57E5F35116D3}"; public const string STATUS_REGION = "StatusRegion {4CEF7A12-1E92-4EED-BD46-F70F07E27662}"; public const string TOOLS_REGION = "ToolsRegion {3C6F99B2-6414-4E06-ACC5-7445944FFA29}"; public const string HARDWARE_INTERFACE_REGION = "HardwareInterfaceRegion {4F16ECD1-D3F5-4BE2-BB00-DD148BAE8A83}"; } 

Note the spelling error in TOOL_DIAGRAM_REGION . It doesn't matter what I messed up because no developer should have introduced it again. I only noticed this error because I was looking at the lines by inserting them here.

-one
source share

All Articles