Autofac和信号器

时间:2013-02-13 07:47:04

标签: signalr autofac

我在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依赖性解析器。任何指针都欢迎,

由于

2 个答案:

答案 0 :(得分:4)

确保在路由集合上调用MapHubs()之前设置解析器,此时对解析器的引用将被传递到基础结构中。在调用MapHubs之后设置一个新的解析器将不会做任何事情。

答案 1 :(得分: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);

    }

}

首先请注意,上面的代码,公共覆盖任务OnDisconnected不能被信任,它不会触发,也不是管理SignalR断开连接的可靠方法,这种方法可能会捕获一些断开连接。幸运的是,根据我的要求,我可以忽略超过一天的连接。

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

最后请注意静态方法是从调用者传递的连接,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();