Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setter Injection or Ambient Context pattern

I have some global components I am not sure how to put them in design. Such as:

  • Settings class: it is interfacing the initial settings of the program, it could be app.config(1way), web.config(1way), hard coded values(1way), or sqldb(2way) behind the scenes.

  • Language class: it contains different language sets, and again, I could have some resx files(1way), hard coded values(1way) or sqldb(2way) behind it.

First question is, should I make these classes setter properties in dependency injection (I use Windsor):

public ISettings Settings {set;}
public ILanguage Language {set;}

Or should I make them ambient context:

string DoSomethingAndReportIt() {
    //do something ...
    var param = Settings.Current.SomeParam;
    //report it ...
    return Language.Current.SomeClass_SomeMethod_Job_Done;
}

I notice there are a few components in .net library that actually use ambient context pattern, e.g. System.Security.Principal, System.Web.ProfileBase, System.Thread.CurrentCulture ...

Do you think it is no harm to make my global classes such as Settings and Language to be ambient context classes? If not, why DI is preferred? Do they take more advantage in unit testing compare to ambient?

Second question is, if DI is better, (I have a feeling that the DI pattern is preferred), what is a good way to proxy the existing ambient classes such as Security.Principal or Profile to follow the DI pattern?

like image 866
Tom Avatar asked Jul 26 '12 12:07

Tom


People also ask

What is ambient context?

The ambient context is known as an anti-pattern of Dependency Injection, in the sense that offers a way to access a dependency direct or indirectly through static members of a class. To illustrate the ambient context in practice, let's see the following example: class LocationManager { ....

Which injection is also called setter injection options constructor injection property injection injection ambient context?

PROPERTY INJECTION is also known as SETTER INJECTION.

What type of design pattern is dependency injection?

In software engineering, dependency injection is a design pattern in which an object or function receives other objects or functions that it depends on. A form of inversion of control, dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs.

What is Property injection?

Property injection is a type of dependency injection where dependencies are provided through properties. Visit the Dependency Injection chapter to learn more about it. Let's understand how we can perform property injection using Unity container. Consider the following example classes.


1 Answers

Ambient context is OK when you need to implement functionality that spans across multiple layers. (In your case you say that the two objects are global) This functionality is known as crosscutting concerns. As you noticed many classes in .NET are implemented as ambient context, like IPrincipal. In order to get a working version of your implementation of ambient context, you will need to have some default value provided to your Settings and Language objects if they are developed as ambient context. My assumption is that you will provide some default implementation of ILanguage and ISettings, and considering that you will use them globally they are good candidates for ambient context.

On the other hand, how often do you plan to use those objects that implement these two interfaces? And, is the existence of the two objects crucial, meaning Settings != null and Language != null? If you really intend to use them in one or two classes, and/or if the existence of the objects is not really important, you might want to go with the setter injection. The setter injection does not really need a default value, so your object can be null.

Personally I am not a fan of ambient context. However I would use it if it turns out to be the most acceptable solution. In case of your implementations I would do something like this: because you will need to initialize objects which implement the two interfaces once and in one location only, you could start with the ambient context. If you realize that you are using it in a very small number of locations, think about refactoring it as a setter injection. If the existence of objects is important think about constructor injection implementation.

like image 171
Husein Roncevic Avatar answered Sep 18 '22 15:09

Husein Roncevic