使用 IoC 容器作为 HttpHandler 的服务定位器

发布于 2024-09-15 20:12:49 字数 2294 浏览 10 评论 0原文

这个问题与我的其他帖子相关。

好吧,经过一番折腾后,我决定这样做。当我运行它时,它似乎工作正常,尽管我在 NUnit 中收到以下错误:无法加载文件或程序集 'Castle.Core,Version=1.0.3.0,Culture=neutral,PublicKeyToken=407dd0808d44fbdc' 或其之一依赖关系。找到的程序集的清单定义与程序集引用不匹配。 (HRESULT 异常:0x80131040)所以不确定那里发生了什么???

只是想知道其他人对设计的看法以及是否有任何明显的“不可以”或改进。即,基本处理程序的构造函数是实例化温莎组件的好地方还是有更好的地方可以做到这一点?正如我在原来的帖子中所说,这种方式背后的想法是保持组件良好的解耦并使单元测试变得容易。我还应该补充一点,我是单元测试和模拟的新手。谢谢!

public abstract class BaseHttpHandler : IHttpHandler
{
    private HttpContext _httpContext;
    private ILogger _logger;
    private IDataRepository _dataRepository;
    protected HttpRequest Request { get { return _httpContext.Request; } }
    protected HttpResponse Response { get { return _httpContext.Response; } }
    protected bool IsRequestFromUAD { get { return Request.UserAgent == null ? false : Request.UserAgent.Equals("UAD"); } }
    protected ILogger Logger { get { return _logger; } }
    protected IDataRepository DataRepository { get { return _dataRepository; } }
    public virtual bool IsReusable { get { return false; } }

    public BaseHttpHandler()
    {
        var container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
        _logger = container.Resolve<ILogger>();
        _dataRepository = container.Resolve<IDataRepository>();
    }

    public void ProcessRequest(HttpContext context)
    {
        _httpContext = context;
        ProcessRequest(new HttpContextWrapper(context));
    }

    public abstract void ProcessRequest(HttpContextBase context);
}

public class UADRecordHttpHandler : BaseHttpHandler
{
    public override void ProcessRequest(HttpContextBase context)
    {
        if (IsRequestFromUAD)
        {
            using (var reader = new StreamReader(context.Request.InputStream))
            {
                string data = reader.ReadToEnd();

                if (Logger != null)
                    Logger.Log(data);

                if(DataRepository != null)
                    DataRepository.Write(data);

                context.Response.Write(data);
            }
        }
        else
            ReturnResponse(HttpStatusCode.BadRequest);
    }
}

This question relates to my other post.

Ok so after a bit more messing around I decided to do it this way. Which seems to work fine when I run it, although I'm getting the following error in NUnit: Could not load file or assembly 'Castle.Core, Version=1.0.3.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040) So not sure what is happening there???

Just wanted to know what others thought about the design and if there are any obvious 'no no's' or improvements. I.e. Is the constructor of the base handler a good place to instantiate the windsor component or is there a better place to do this? As I said in the original post the idea behind doing things this way was to keep the components nicely decoupled and to make unit testing easy. I should also add I'm new to unit testing, mocking. Thanks!

public abstract class BaseHttpHandler : IHttpHandler
{
    private HttpContext _httpContext;
    private ILogger _logger;
    private IDataRepository _dataRepository;
    protected HttpRequest Request { get { return _httpContext.Request; } }
    protected HttpResponse Response { get { return _httpContext.Response; } }
    protected bool IsRequestFromUAD { get { return Request.UserAgent == null ? false : Request.UserAgent.Equals("UAD"); } }
    protected ILogger Logger { get { return _logger; } }
    protected IDataRepository DataRepository { get { return _dataRepository; } }
    public virtual bool IsReusable { get { return false; } }

    public BaseHttpHandler()
    {
        var container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
        _logger = container.Resolve<ILogger>();
        _dataRepository = container.Resolve<IDataRepository>();
    }

    public void ProcessRequest(HttpContext context)
    {
        _httpContext = context;
        ProcessRequest(new HttpContextWrapper(context));
    }

    public abstract void ProcessRequest(HttpContextBase context);
}

public class UADRecordHttpHandler : BaseHttpHandler
{
    public override void ProcessRequest(HttpContextBase context)
    {
        if (IsRequestFromUAD)
        {
            using (var reader = new StreamReader(context.Request.InputStream))
            {
                string data = reader.ReadToEnd();

                if (Logger != null)
                    Logger.Log(data);

                if(DataRepository != null)
                    DataRepository.Write(data);

                context.Response.Write(data);
            }
        }
        else
            ReturnResponse(HttpStatusCode.BadRequest);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

疯了 2024-09-22 20:12:49

你在这里所做的事情是一件非常糟糕的事情。每个应用程序应该有一个容器实例,而使用此代码,每个请求都会有一个容器实例。

That's a very bad thing to do, what you're doing here. You should have one instance of the container per application, while with this code you will have one per each request.

北城挽邺 2024-09-22 20:12:49

关于 NUnit 中的错误:确保 GAC 中没有其他版本的 Castle 程序集。如果是这样,请卸载它们。

关于您的 BaseHttpHandler:此实现的问题是您正在创建一个新容器。相反,正如 Krzysztof 所说,每个应用程序使用一个容器。使用静态服务定位器,例如CommonServiceLocator。 (我从不推荐这个,但它是少数几个确实有意义的地方之一)。

About the error in NUnit: make sure you don't have other versions of Castle assemblies in the GAC. If so, uninstall them.

About your BaseHttpHandler: the problem with this implementation is that you're creating a new container. Instead, use a single container per application, like Krzysztof said. Use a static service locator, e.g. CommonServiceLocator. (I never recommend this but it's one of the few places where it does make sense).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文