1

我已经在 Autofac 组上发布了这个,但没有运气。

我正在使用来自 Nuget 的 Autofac3,0.1、SignalR 1.0.0pre2 和 Autofac.SignalR.3.0.0 包。我正在使用 Autofac 注册类型,但在分辨率上我得到了

“没有为此对象定义无参数构造函数。”

错误

我的中心看起来像

public class UserHub : AuthenticatingHub
{
    private readonly IUserService _userService;

    public UserHub(IUserService userService)
    {
        _userService = userService;
    }

我的容器构建器是这样的:

        var builder = new ContainerBuilder();
        builder.RegisterControllers(typeof(MvcApplication).Assembly);

        var serviceAssemblies = Assembly.Load("Services");
        builder.RegisterAssemblyTypes(serviceAssemblies).AsImplementedInterfaces();
        builder.RegisterType<UserHub>();

        var container = builder.Build();

        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        GlobalHost.DependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(container);

“服务”引用 IUserService 的位置

这是与以前版本的 SignalR 和 Autofac 一起使用但使用不同的 Autofac 依赖解析器的代码。欢迎任何指点,

谢谢

4

2 回答 2

4

请务必在路由集合上调用 MapHubs() 之前设置您的解析器,此时对解析器的引用将被传递到那里的基础设施中。在调用 MapHubs 后设置新的解析器不会做任何事情。

于 2013-02-13T09:53:25.907 回答
1

互联网上的文档中缺少很多内容。我写了一篇关于同时使用 SignalR 2.0 和 Autofac 的文章,因为 Autofac 的文档不完整:

我写了一篇关于这个的博客,但我把那个网站写下来了,这是那篇博客文章的 HTML:

在 MVC 应用程序中通过 Autofac 大量使用 DI 并且在使用 Signalr 2.0 时遇到问题?

您是否遵循 Autofacs 文档并安装了 Autofac.SignalR Nuget 包: https ://code.google.com/p/autofac/wiki/SignalRIntegration

Autofac 的文档存在多个问题,Autofac.Singalr Nuget 包适用于 SignalR 1.0。

所以首先,让我们使用 SignalR 2.0 进行修复。您只需将 Autofac.SignalR 包朝正确的方向轻推,将以下内容添加到您的 Web.config 中:

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

        <dependentAssembly>

            <assemblyIdentity name="Microsoft.AspNet.SignalR.Core" publicKeyToken="31bf3856ad364e35" culture="" />

            <bindingRedirect oldVersion="1.0.0.0" newVersion="2.1.1.0" />

        </dependentAssembly>

    </assemblyBinding>

</runtime>

现在实际工作的实际代码:

public interface IConversationHub

{

    System.Threading.Tasks.Task OnConnected();



    void SendNotifications(long _account_id, int _partition_id, List<long> _userIds,

        DTO.ConversationEventMessage _message);

}



[Authorize]

public class ConversationHub : Hub, IConversationHub

{

    readonly ILifetimeScope _hubLifetimeScope;

    private uTextAPP.AppLayer.IManageUsers _ManageUsers { get; set; }

    private uTextAPP.AppLayer.IManageUserConnections _ManageUserConnections { get; set; }

    private uTextDDD.ServiceLayer.IReportUserConnections _ReportUserConnections { get; set; }



    public ConversationHub(ILifetimeScope lifetimeScope)

    {

        // Create a lifetime scope for the hub.

        _hubLifetimeScope = lifetimeScope.BeginLifetimeScope();



        // Resolve dependencies from the hub lifetime scope.

        _ManageUsers = _hubLifetimeScope.Resolve<uTextAPP.AppLayer.IManageUsers>();

        _ManageUserConnections = _hubLifetimeScope.Resolve<uTextAPP.AppLayer.IManageUserConnections>();

        _ReportUserConnections = _hubLifetimeScope.Resolve<uTextDDD.ServiceLayer.IReportUserConnections>();

    }



    public override System.Threading.Tasks.Task OnConnected()

    {

        //var username = Context.User.Identity.Name; //this is the user_id!! yay!

        var user = _ManageUsers.GetCurrentUser();

        var _issues = new Issues();



        if (user == null || user.account_id == 0)

            return base.OnConnected();



        var conn = new user_connection

               {

                   connection_id = Context.ConnectionId,

                   user_id = user.user_id

               };



        _ManageUserConnections.CreateUserConnection(user.account_id, user.user_id, user.partition_id, conn, _issues);



        return base.OnConnected();

    }





    internal static void SendNotifications(long _account_id, int _partition_id, List<long> _userIds, DTO.ConversationEventMessage _message, IEnumerable<uTextDTO.AppLayer.user_connection> _connections )

    {

        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<ConversationHub>();





        if (_connections == null) return;



        foreach (var c in _connections)

        {

            if (_userIds.Any(_userIds.Contains))

            {

                if (context.Clients.Client(c.connection_id) != null)

                {

                    context.Clients.Client(c.connection_id).receiveNotification(_message);

                }

            }

        }

    }





    public void SendNotifications(long _account_id, int _partition_id, List<long> _userIds, DTO.ConversationEventMessage _message)

    {

          var _issues = new Issues();

        SendMessage(_account_id, _partition_id, _userIds, _message, _ReportUserConnections.GetAllUserConnectionsByDaysBack(_account_id, -1L, _partition_id, 1, _issues))

        ;



    }



    public override Task OnDisconnected(bool stopCalled)

    {

        var user = _ManageUsers.GetCurrentUser();

        var _issues = new Issues();



        if (user == null || user.account_id == 0)

            return base.OnConnected();



        var original = _ManageUserConnections.GetUserConnectionByConnectionId(user.account_id, user.partition_id,

            user.partition_id, Context.ConnectionId, _issues);



        if (original != null && original.user_connection_id != 0L)

        {

            var mod = new user_connection().CopyModelExt(original);

            mod.is_active = false;



            _ManageUserConnections.UpdateUserConnection(user.account_id, user.user_id, user.partition_id, original.user_connection_id,mod, original, _issues);

        }



        return base.OnDisconnected(stopCalled);

    }



    protected override void Dispose(bool disposing)

    {

        // Dipose the hub lifetime scope when the hub is disposed.

        if (disposing && _hubLifetimeScope != null)

            _hubLifetimeScope.Dispose();



        base.Dispose(disposing);

    }

}

首先,请注意上面的代码,公共覆盖 Task OnDisconnected 不可信,它不会触发并且不是管理与 SignalR 断开连接的可靠方法,此方法可能会捕获一些断开连接。幸运的是,对于我的要求,我可以忽略超过一天的连接。

接下来注意,使用上面的代码,内部静态 void SendNotifications。SendNotifications 必须是静态的,以便 SignalR 上下文在访问时不会引发运行时错误。

最后请注意,静态方法是从调用者传递的连接,即 SendNotifications 的公共公开方法。我需要 SendNotifications 中的 IReportUserConnections 实例,但 IReportUserConnections 不是静态的,也不能是静态的,无法由 Autofac 正确注入。所以我不能在静态 void SendNotifications 中使用 IReportsUserConnections,所以我用公共版本的 SendNotifications 解决了这个问题。

对于 Autofac 容器:

public static class SimpleInjectorInitializer

{

    public static IContainer Container;



    public static void Initialize()

    {

        var builder = new ContainerBuilder();



                   // Register the SignalR hubs.

                    builder.RegisterHubs(typeof(uTextAPP.SignalR.ConversationHub).Assembly);



        uTextMVC.RegisterMe.Register(builder);



        Container = builder.Build();

        DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(Container));



        var signalRDependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(Container);

        GlobalHost.DependencyResolver = signalRDependencyResolver;

    }

}

互联网上缺少的重要部分之一,如何实际使用您的 IoC 注入的 ConversationHub 发送通知:

public Lazy _ConversationHub { get; set; }
_ConversationHub.Value.SendNotifications(account.account_id, account.partition_id, userIds, convoEv);

您必须确保在 Register.me 中使用 Autofac 注册 Hub,以便初始化 _ConversationHub:

  container.RegisterType<SignalR.ConversationHub>().As<SignalR.IConversationHub>().InstancePerLifetimeScope().PropertiesAutowired();
于 2014-08-24T05:07:18.997 回答