Fabio Milheiro
Fabio Milheiro

Reputation: 8474

What dependency injection pattern to use for a MessageProvider?

I have a ContactController where I set up a message in the TempData (this is to display a message in the screen after successful submission) and in the layout, there's a partial _Message.cshtml that is supposed to render the message, if any. Method signatures below:

List<Message> GetMessages(IDictionary<string, object> dictionary);
void SetMessage(IDictionary<string, object> dictionary, string body, MessageType type);

Initially I thought about having a MessageProvider dependency injected in the constructor. But then it occurred to me: What if I need do this in other controllers? Besides, for me to use it in the partial view, I need to resolve the implementation from the container which I think is an acceptable solution to use in a class that extends WebViewPage (considering I am not going to unit test it).

public MyCustomViewPage()
{
  this.MessageProvider = DependencyResolver.Current.GetService<MessageProvider>();
}

public MessageProvider MessageProvider { get; set; }

But can we avoid the Service Locator anti-pattern using another dependency injection pattern?

I was thinking this MessageProvider has a good default implementation and since we might need to use this in more controllers in the future, this might be a good candidate for Ambient Context design pattern as per the book Dependency Injection in .NET by Mark Seemann.

This way, I would eliminate the potential problem of having to change other controller constructors in the future in case I happen to have to set messages in them, I would eliminate the need to use the Service Locator anti-pattern in the MyCustomViewPage constructor and my controller will still be testable.

I would then use the following code in partial view:

var messages = MessageProvider.Current.GetMessages()

And the following code in my controllers:

MessageProvider.Current.SetMessage("Message sent successfully.", MessageType.Success);

And in my test fixtures (if I would actually need another implementation):

MessageProvider.SetMessageProvider(otherImplementation);

Do you think this approach makes sense? Any downsides I might be missing?

Upvotes: 0

Views: 58

Answers (1)

Fabio Milheiro
Fabio Milheiro

Reputation: 8474

To anyone who might be looking for the same answer in the future, I decided to use Ambient Context for this because of the reasons I mentioned in the quesiton.

Upvotes: 0

Related Questions