I have a complex entity (Message) that has quite a hefty constructor (13 parameters), some of these parameters are in turn entities (Verb).
There are a number of things I need a repository of another Entity for (e.g. for some defaults).
What is a good way of using IoC and keeping the code clean / best practice?
Simplified code (I’d put the default verb list as a static object constructed by the static constructor personally, its the simplest if naff example of why my Message entity needs some sort of IRepositry).
private static IVerbRepository verbRepository;
static Message()
{
using (IKernel kernel = new StandardKernel())
{
verbRepository = kernel.Get<IVerbRepository>();
}
}
public Message(int id, string precis,
DateTime created, DateTime validTo,
PriorityType priority, Source source, SID createdBy,
string content = null, string helpText = null,
DateTime? validFrom = null, bool emailOnExpiry = false,
IEnumerable<SID> targetUsers = null,
IOrderedEnumerable<MessageVerb> verbs = null) : base(id)
{
Verbs = verbs ??
new List<MessageVerb>
{
new MessageVerb(
verbRepository.GetByName("Acknowledge"), true,
string.Empty)
}.OrderBy(x => x.IsDefault);
Precis = precis;
Created = created;
ValidTo = validTo;
Priority = priority;
Source = source;
CreatedBy = createdBy;
Content = content;
HelpText = helpText;
ValidFrom = validFrom;
EmailOnExpiry = emailOnExpiry;
TargetUsers = targetUsers;
}
The common practice seems to be to add an additional parameter to the constructor. I don’t get how this is better? It means everytime you want to create a message, you need to write code to retrieve the repository. Assumning you wrap this around in a Factory, it doesn’t make sense to allow (logically if not actually) have different repositories for message entites?
Edit 1
Based on the first solutions the code would like this,
public Message(IVerbRepository verbRepository ...) { }
Elsewhere in the same domain assembly
public MessageService
{
private IVerbRepository VerbRepository {get; set;}
public static IOrderedEnumerable<MessageVerb> DefaultVerb {get;}
}
Much higher up outside of my DDD (let’s say my web services that accept creations of messages)
public class MessageWebService
{
private static IVerbRepository _verbRepository;
public void AddMessage(some parameters)
{
var message = new Message(_verbRepository, ...);
}
}
There’re two flavors of IoC: Service Locator, which you’re using, and Dependency Injection, which you’re asking about.
As of now, Service Locator is considered a kind of anti-pattern, because it introduces implicit dependencies (dependencies you can’t figure out by looking at class’s public interface) and makes testing harder.
Dependency Injection, on the other hand, does not have these problems, but tends to be more verbose in class declaration.
Now, regarding your question.
It is explicit. You can see that your class depends on this or that service. BTW, your class doesn’t, it only uses verb repository for locating default verb (which can be easily moved outside of class).
It does when you think of testing. You should be easily able to substitute any service your CUT is depending on with testable implementation (stub).