Caching 有时在域类中使用服务定位器模式可以吗?

Caching 有时在域类中使用服务定位器模式可以吗?,caching,dependency-injection,httpwebrequest,domain-driven-design,service-locator,Caching,Dependency Injection,Httpwebrequest,Domain Driven Design,Service Locator,这个问题可能更适合程序员堆栈。如果是的话,我会提出动议。然而,我想我可能会在这里得到更多的答案 到目前为止,我的域中的所有接口依赖项都是使用来自执行程序集的DI来解决的,目前它是一个.NET MVC3项目(+Unity IoC容器)。然而,我遇到了一个场景,我认为服务定位器可能是一个更好的选择 域中有一个实体存储(缓存)URL中的内容。具体地说,它存储来自元数据URL的SAML2 EntityDescriptor XML。我有一个接口IConsumeHttp和一个方法: public inter

这个问题可能更适合程序员堆栈。如果是的话,我会提出动议。然而,我想我可能会在这里得到更多的答案

到目前为止,我的域中的所有接口依赖项都是使用来自执行程序集的DI来解决的,目前它是一个.NET MVC3项目(+Unity IoC容器)。然而,我遇到了一个场景,我认为服务定位器可能是一个更好的选择

域中有一个实体存储(缓存)URL中的内容。具体地说,它存储来自元数据URL的SAML2 EntityDescriptor XML。我有一个接口IConsumeHttp和一个方法:

public interface IConsumeHttp
{
    string Get(string url);
}
当前实现使用System.Net中的静态WebRequest类:

public class WebRequestHttpConsumer : IConsumeHttp
{
    public string Get(string url)
    {
        string content = null;
        var request = WebRequest.Create(url);
        var response = request.GetResponse();
        var stream = response.GetResponseStream();
        if (stream != null)
        {
            var reader = new StreamReader(stream);
            content = reader.ReadToEnd();
            reader.Close();
            stream.Close();
        }
        response.Close();
        return content;
    }
}
缓存XML内容的实体作为非根存在于更大的实体聚合中。对于聚合的其余部分,我将实现一个有点大的Facade模式,它是MVC控制器的公共端点。我可以在facade构造函数中注入IConsumeHttp依赖项,如下所示:

public AnAggregateFacade(IDataContext dataContext, IConsumeHttp httpClient)
{
    ...
我看到的问题是facade中只有一个方法依赖于这个接口,因此为整个facade注入它似乎很愚蠢。
WebRequestHttpConsumer
类的对象创建不应该增加很多开销,但域不知道这一点

相反,我考虑将实体的所有缓存逻辑移出到一个单独的静态工厂类中。不过,代码将取决于
IConsumeHttp
。因此,我考虑在静态工厂方法中使用静态服务定位器来解析IConsumeHttp,但仅当需要初始化或刷新缓存的XML时

我的问题:这是个坏主意吗?在我看来,域应该负责确保XML元数据被适当地缓存。域定期执行此操作,作为其他相关操作的一部分(例如获取SAML Authn请求和响应的元数据、更新SAML EntityID或元数据URL等)。还是我太担心了

在我看来,域名有责任 确保XML元数据被适当地缓存

我不确定这一点,除非你的领域真的是关于元数据操作、http请求等等。对于非技术领域的“普通”应用程序,我宁愿在基础设施/技术服务层处理缓存问题

我看到的问题是facade中只有一个方法具有 依赖于此接口,因此为 整面

显然,外观通常不适合构造函数注入,因为它们自然倾向于指向许多依赖项。你可以考虑其他类型的注射,或者,正如你指出的,使用定位器。但我个人要做的是问问自己,外观是否真的合适,并考虑使用细粒度的对象,而不是相同的大接口在我的所有控制器。这将允许更多的模块化和特别的注入,而不是预先膨胀一个巨大的对象


但这可能只是因为我不是一个门面迷;)

在您对@ian31的评论中,您提到“似乎让控制器确保域具有正确的XML过于精细,给了客户端太多的责任”。出于这个原因,我希望控制器向其服务/存储库(可以实现缓存层)请求正确的当前XML。对我来说,这个职责对域实体的要求很高

但是,如果您对所概述的职责没有异议,并且您提到对象创建的开销不大,那么我认为将IConsumeHttp保留在实体中是可以的。

为了履行这一职责,另一种方法是将此接口向下移动到子实体中。如果您的案例可以做到这一点,至少依赖关系仅限于需要它的场景。

相关:我认为这是一个正确的问题。@Steven感谢您的链接、信任投票以及您关于如何在架构的查询+命令端运行的博客。非常有趣的东西。谢谢你的投入。域与HTTP无关,也不引用System.Web、MVC或任何类似的DLL,这就是我将HttpConsumer包装在接口中的原因。这是在域中使用它的唯一情况。控制器处理SAML http事务,并将元数据用于ops,例如发送Authn请求。让控制器确保域具有正确的XML似乎过于细粒度,给了客户端太多的责任。域已经知道该URL,并且可以自己执行此操作。不过,你说得有道理,我正在研究其他模式。谢谢你的回答,很抱歉回复太晚。在这个项目中,没有服务层。MVC项目使用factory和facade模式直接访问域表面。IConsumeHttp依赖项不在域实体上,而是在另一个域类上。元数据最终存储在域实体属性上,但它不是执行HTTP查找的实体。另外,当我说“缓存”时,我不是指使用内存缓存。我的意思是XML内容存储在实体上,并使用元数据URL定期刷新。