【问题标题】:Ninject Topshelf Microsoft.Owin.HostingNinject Topshelf Microsoft.Owin.Hosting
【发布时间】:2014-06-26 17:27:09
【问题描述】:

如何利用 Topshelf.Ninject 并合并 OwinNinjectDependencyResolver(来自 Ninject.Web.WebApi.OwinHost)?

我可以让它工作,但我需要两次实例化 Ninject 内核(一次用于 Topshelf,一次用于我的 HttpConfiguration.DependencyResolver。这似乎不是使用 Ninject 的正确方法。

任何与此特定设计相关的帮助或示例代码都会非常有帮助。

【问题讨论】:

  • 我面临着完全相同的问题。

标签: ninject owin topshelf


【解决方案1】:

所以我遇到了同样的问题,我设法解决了。

关键是:

  • 不使用 [assembly: OwinStartup(...)] 属性来引导 OWIN。
  • 使用 Ninject 将 IKernel 注入到用于配置 Topshelf 的服务类中。
  • 使用Microsoft.Owin.Hosting.WebApp 类的Start(StartOptions options, Action<Owin.IAppBuilder> startup) 方法启动自托管网络应用。
  • 通过启动操作将注入的内核传递给 OWIN 引导例程。
  • 在 OWIN 启动例程中调用 appBuilder.UseNinjectMiddleware(() => kernel); 时使用传入的内核引用,而不是 appBuilder.UseNinjectMiddleware(CreateKernel);
  • 利润。

完整的解决方案如下:

  1. 创建一个名为 BackgroundProcessor 的控制台应用程序解决方案。
  2. 使用 NuGet 将下面Packages.config 列表中列出的包添加到解决方案中。
  3. 使用下面的列表将App.config 添加到解决方案中。
  4. 将下面提供的每个代码文件添加到解决方案中;我提供了完整的清单,因为代码行对 using 语句非常敏感,因为解决方案使用的库大量使用扩展方法。
  5. 编译并运行项目。
  6. 通过在本地计算机上点击 URL http://localhost:9000/test 来测试解决方案。

Packages.config

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.AspNet.WebApi" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.Owin.Host.HttpListener" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.Owin.Hosting" version="2.1.0" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
  <package id="Ninject" version="3.2.2.0" targetFramework="net45" />
  <package id="Ninject.Extensions.ContextPreservation" version="3.2.0.0" targetFramework="net45" />
  <package id="Ninject.Extensions.NamedScope" version="3.2.0.0" targetFramework="net45" />
  <package id="Ninject.Web.Common" version="3.2.2.0" targetFramework="net45" />
  <package id="Ninject.Web.Common.OwinHost" version="3.2.2.0" targetFramework="net45" />
  <package id="Ninject.Web.WebApi" version="3.2.0.0" targetFramework="net45" />
  <package id="Ninject.Web.WebApi.OwinHost" version="3.2.1.0" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />
  <package id="Topshelf" version="3.1.3" targetFramework="net45" />
  <package id="Topshelf.Ninject" version="0.3.0.0" targetFramework="net45" />
</packages>

App.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Topshelf" publicKeyToken="b800c4cfcdeea87b" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.1.122.0" newVersion="3.1.122.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Ninject" publicKeyToken="c7192dc5380945e7" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.2.0.0" newVersion="3.2.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ninject;
using Topshelf;
using Topshelf.Ninject;

namespace BackgroundProcessor
{
    using Modules;
    using Services;

    public class Program
    {
        public static int Main(string[] args)
        {
            var exitCode = HostFactory.Run
            (
                c =>
                {
                    c.UseNinject(new Module());

                    c.Service<Service>
                    (
                        sc =>
                        {
                            sc.ConstructUsingNinject();

                            sc.WhenStarted((service, hostControl) => service.Start(hostControl));
                            sc.WhenStopped((service, hostControl) => service.Stop(hostControl));
                        }
                    );

                    c.SetServiceName("BackgroundProcessorSvc");
                    c.SetDisplayName("Background Processor");
                    c.SetDescription("Processes things in the background");

                    c.EnablePauseAndContinue();
                    c.EnableShutdown();

                    c.StartAutomaticallyDelayed();
                    c.RunAsLocalSystem();
                }
            );

            return (int)exitCode;
        }
    }
}

Modules\Module.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject.Modules;

namespace BackgroundProcessor
{
    using Contracts;
    using Services;

    namespace Modules
    {
        public class Module : NinjectModule
        {
            public override void Load()
            {
                Bind<IService>().To<Service>();
            }
        }
    }
}

Contracts\IService.cs

using System;

namespace BackgroundProcessor
{
    namespace Contracts
    {
        public interface IService
        {
            bool Start(Topshelf.HostControl hostControl);

            bool Stop(Topshelf.HostControl hostControl);
        }
    }
}

Services\Service.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Owin.Hosting;
using Ninject;
using Topshelf;

namespace BackgroundProcessor
{
    using Configs;
    using Contracts;

    namespace Services
    {
        public class Service : IService
        {
            private readonly IKernel kernel;

            public Service(IKernel kernel)
                : base()
            {
                this.kernel = kernel;
            }

            protected IKernel Kernel
            {
                get
                {
                    return this.kernel;
                }
            }

            protected IDisposable WebAppHolder
            {
                get;
                set;
            }

            protected int Port
            {
                get
                {
                    return 9000;
                }
            }

            public bool Start(HostControl hostControl)
            {
                if (WebAppHolder == null)
                {
                    WebAppHolder = WebApp.Start(new StartOptions { Port = Port }, appBuilder =>
                    {
                        new StartupConfig().Configure(appBuilder, Kernel);
                    });
                }

                return true;
            }

            public bool Stop(HostControl hostControl)
            {
                if (WebAppHolder != null)
                {
                    WebAppHolder.Dispose();
                    WebAppHolder = null;
                }

                return true;
            }
        }
    }
}

Configs\StartupConfig.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Http;
using Ninject;
using Ninject.Web.Common.OwinHost;
using Ninject.Web.WebApi.OwinHost;
using Owin;

namespace BackgroundProcessor
{
    namespace Configs
    {
        public class StartupConfig
        {
            public void Configure(IAppBuilder appBuilder, IKernel kernel)
            {
                var config = new HttpConfiguration();

                config.MapHttpAttributeRoutes();
                config.MapDefinedRoutes();

                appBuilder.UseNinjectMiddleware(() => kernel);
                appBuilder.UseNinjectWebApi(config);
            }
        }
    }
}

Configs\RoutesConfig.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

namespace BackgroundProcessor
{
    namespace Configs
    {
        public static class RoutesConfig
        {
            public static void MapDefinedRoutes(this HttpConfiguration config)
            {
                config.Routes.MapHttpRoute
                (
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new
                    {
                        id = RouteParameter.Optional
                    }
                );
            }
        }
    }
}

Controllers\TestController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

namespace BackgroundProcessor
{
    namespace Controllers
    {
        [RoutePrefix("test")]
        public class TestController : ApiController
        {
            [HttpGet]
            [Route("")]
            public HttpResponseMessage Index()
            {
                return Request.CreateResponse<string>(HttpStatusCode.OK, "Hello world!");
            }
        }
    }
}

【讨论】:

  • Umar,感谢您提供的非常广泛的回答。我仍然面临这个问题,所以我会尝试实施您的解决方案,并让您知道结果如何。
  • 这是a zip file containing the whole solution 的链接。这可能比手动重新创建整个项目更有帮助。
  • 太棒了。 zip 文件会很有帮助。
  • 如果示例对您有帮助,请不要忘记将答案标记为已接受(并且也可能投票赞成 :))
  • 我还不能投票,但我会尽快达到那个级别。
猜你喜欢
  • 2023-03-19
  • 2020-12-14
  • 2016-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
相关资源
最近更新 更多