【问题标题】:use dependency injection in Signalr 2.0 self-host?在 Signalr 2.0 自托管中使用依赖注入?
【发布时间】:2014-01-27 18:47:13
【问题描述】:

在自托管应用程序中使用 SignalR 2.0,来自these instructions,您将拥有如下内容:

class Startup
{
   public void Configuration(IAppBuilder app)
   {
       app.MapSignalR(new HubConfiguration { Resolver = ... });
   }
}
class Program
{
    static void Main(string[] args)
    {
        using (WebApp.Start("http://localhost:8080")) // constructs Startup instance internally
        {
            Console.WriteLine("Server running on {0}", url);
            Console.ReadLine();
        }
    }
}

您会注意到 Startup 类实例是使用一些幕后魔法创建的。我不知道如何填写对它的依赖项。有什么方法可以覆盖 Startup 类的构造,以便我可以将依赖项注入其中?

【问题讨论】:

    标签: c# asp.net dependency-injection signalr self-hosting


    【解决方案1】:

    您可以简单地使用 Katana 的 ServiceProvider 注册 Startup 的构造函数参数,而不是替换 IAppActivator。

    默认的 IAppActivator 将为您解析与 Startup 构造函数的参数类型匹配的任何服务。唯一的缺点是你不能使用 WebApp.Start,因为它不会暴露 ServiceProvider:

    public class MyService : IMyService
    {
        private readonly IMyOtherService _myOtherService;
    
        // Services will be recursively resolved by Katana's ServiceProvider
        public MyService(IMyOtherService myOtherService)
        {
            _myOtherService = myOtherService;
        }
    
        // Implementation
    }
    
    public class Startup
    {
       private readonly IMyService _myService;
    
       // Startup must have exactly one constructor.
       public Startup(IMyService myService)
       {
           _myService = myService
       }
    
       public void Configuration(IAppBuilder app)
       {
           app.MapSignalR(new HubConfiguration { Resolver = ... });
       }
    }
    

    using System;
    using Microsoft.Owin.Hosting;
    using Microsoft.Owin.Hosting.Services;
    using Microsoft.Owin.Hosting.Starter;
    
    public class Program
    {
        static void Main(string[] args)
        {
            var url = "http://localhost:8080";
    
            var services = (ServiceProvider)ServicesFactory.Create();
            var options = new StartOptions(url);
    
            services.Add<IMyOtherService, MyOtherService>();
            services.Add<IMyService, MyService>();
    
            var starter = services.GetService<IHostingStarter>();
    
            using (starter.Start(options)) // constructs Startup instance internally
            {
                Console.WriteLine("Server running on {0}", url);
                Console.ReadLine();
            }
        }
    }
    

    我将 WebApp.Start 的默认实现复制到 Program.Main 中,但不是立即调用 IHostingStarter.Start,而是先添加自定义服务:http://katanaproject.codeplex.com/SourceControl/changeset/view/c726b87e90c05677a256ca1821bac481f402d6bd#src/Microsoft.Owin.Hosting/WebApp.cs

    ServiceProvider 还有很多其他重载。如果需要,请添加:http://msdn.microsoft.com/en-us/library/microsoft.owin.hosting.services.serviceprovider(v=vs.111).aspx

    这应该比使用 StartOptions.Settings 替换 Katana 的 IAppActivator 简单得多,就像我在之前的回答中建议的那样。

    不过,我将保留我之前的答案,因为它确实更详细地解释了 Startup 类的构建方式以及如何使用 Settings 字典替换默认服务实现。

    【讨论】:

    • 我必须将 ServicesFactory.Create() 转换为 ServiceProvider 以获取 Add 方法。这是预期的吗?
    • 你说得对。我更新了我的示例,将返回值从ServicesFactory.Create() 转换为ServiceProvider。您可以通过查看Create 的实现来判断这是安全的:katanaproject.codeplex.com/SourceControl/changeset/view/…
    • 这太复杂了。将 Startup 类中的内容移动到 lambda 函数中,如下所示:WebApp.Start(baseAddress, app =&gt; { app.MapSignalR(new HubConfiguration { Resolver = ... }); }。那么你就不需要在启动类中注入东西了,你可以将它们注入到名为WebApp.Start的类中,并通过闭包来引用它们。
    【解决方案2】:

    在这里查看依赖注入信息:http://www.asp.net/signalr/overview/signalr-20/extensibility/dependency-injection

    应该有你需要知道的一切:)

    希望这会有所帮助!

    【讨论】:

    • 我已经阅读了那个特定的文件。唉,它只适用于 IIS 而不是自托管的东西。你会注意到他们使用App.MapSignalR(config)的方法在自托管时不存在。
    • 再通读一遍...查看 IoC 容器部分的正上方
    • IoC 容器部分的正上方是关于注入 Hub 类的讨论。我在那里没有问题。我想注入集线器注入器。
    • @Brannon App.MapSignalR(config) 在自托管时绝对存在!如果您想“注入集线器注入器”,您可以替换 SignalR 的 IAssemblyLocator、IHubDescriptorProvider 和/或 IHubActivator。我在这里简单解释一下这三个接口的用途:stackoverflow.com/questions/21111436/…
    • @halter73,你能告诉我 Startup 类是在代码中的什么位置构造的吗?而且我仍然不相信 App == WebApp。
    【解决方案3】:
    class Startup
    {
       private readonly IDependencyResolver _resolver;
    
       public Startup(IDependencyResolver resolver)
       {
            _resolver = resolver;
       }
    
       public void Configuration(IAppBuilder app)
       {
           app.MapSignalR(new HubConfiguration { Resolver = _resolver; });
       }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Startup startup = new Statrtup(new MyResolver());
            using (WebApp.Start("http://localhost:8080", startup.Configuration))
            {
                Console.WriteLine("Server running on {0}", url);
                Console.ReadLine();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-03
      • 2015-10-10
      相关资源
      最近更新 更多