我有一个复杂的实体 (Message
),它有一个相当庞大的构造函数(13 个参数),其中一些参数又是实体(Verb
)。
有很多事情我需要另一个实体的存储库(例如,对于某些默认值)。
什么是使用 IoC 并保持代码清洁的好方法/最佳实践?
简化的代码(我将默认动词列表作为由静态构造函数亲自构造的静态对象,这是最简单的例子,如果我的 Message 实体需要某种 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;
}
通常的做法似乎是向构造函数添加一个额外的参数。我不明白这怎么更好?这意味着每次您想要创建消息时,都需要编写代码来检索存储库。假设您将其包装在一个工厂中,允许(逻辑上如果不是实际上)有不同的消息实体存储库是没有意义的吗?
编辑 1
基于第一个解决方案,代码会像这样,
public Message(IVerbRepository verbRepository ...) { }
在同一个域程序集的其他地方
public MessageService
{
private IVerbRepository VerbRepository {get; set;}
public static IOrderedEnumerable<MessageVerb> DefaultVerb {get;}
}
在我的 DDD 之外更高(假设我的网络服务接受消息的创建)
public class MessageWebService
{
private static IVerbRepository _verbRepository;
public void AddMessage(some parameters)
{
var message = new Message(_verbRepository, ...);
}
}
最佳答案
IoC 有两种类型:Service Locator,您正在使用,Dependency Injection,您正在询问。
截至目前,Service Locator 被认为是一种反模式,因为它引入了隐式依赖项(您无法通过查看类的公共(public)接口(interface)来弄清楚的依赖项)并使测试更加困难。
另一方面,依赖注入(inject)没有这些问题,但在类声明中往往更加冗长。
现在,关于你的问题。
I don't get how this is better?
这是明确的。你可以看到你的类(class)依赖于这个或那个服务。顺便说一句,你的类没有,它只使用动词库来定位默认动词(可以很容易地移出类)。
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?
当您想到测试时,它确实如此。您应该能够轻松地用可测试的实现( stub )替换您的 CUT 所依赖的任何服务。
关于c# - 良好的设计 DDD 和 IoC,如何将 IRepository 注入(inject)模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12158408/