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



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

到目前为止,我域中的所有接口依赖项都是使用执行程序集的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中只有一个方法具有依赖于这个接口,所以为全立面

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

但这可能只是因为我不是Facade的铁杆粉丝;)

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

然而,如果您对所概述的职责感到满意,并且您提到对象创建没有太多开销,那么我认为将IConsumeHttp留在实体中是可以的
坚持这一职责,另一种方法可能是将此接口向下移动到子实体中。如果这对您的案例来说是可能的,那么至少依赖关系被限制在需要它的场景中。

最新更新