避免依赖注入中的依赖循环

问题描述 投票:0回答:1

C#Windows窗体应用程序。我有一个Hub和一个班级。两者都应该互相参考。这是因为:

  1. 从中心我需要调用类的方法
  2. 从我需要检索我的Hub的类

现在我可以使用Autofac做第一点了:

using Autofac;
using Autofac.Integration.SignalR;
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Hosting;
using Owin;
using MyProject.Classes;
using System;
using System.Reflection;
using System.Windows.Forms;

namespace MyProject
{
    static class Program
    {
        static IDisposable webApp;

        [STAThread]
        static void Main()
        {
            string url = "http://localhost:8080";
            webApp = WebApp.Start(url);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Engine());
        }
    }

    class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(CorsOptions.AllowAll);

            var builder = new ContainerBuilder();
            var config = new HubConfiguration();
            builder.RegisterHubs(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            builder.RegisterType<Erp>().PropertiesAutowired().InstancePerLifetimeScope();
            var container = builder.Build();
            config.Resolver = new AutofacDependencyResolver(container);
            app.UseAutofacMiddleware(container);
            app.MapSignalR(config);
        }
    }
}

枢纽:

using Microsoft.AspNet.SignalR;
using MyProject.Classes;
using System;
using System.Threading.Tasks;

namespace MyProject.Hubs
{
    public class LiveHub : Hub
    {
        private readonly Erp _erp;

        public LiveHub(Erp erp)
        {
            _erp = erp;
        }

        public override Task OnConnected()
        {
            _erp.someMethod();
            return base.OnConnected();
        }
    }
}

在这里Erp.cs:

public class Erp
{
    public Erp()
    {
    }

    public void SomeMethod()
    {
        // do something
    }

    public void SomeOtherMethod()
    {
        // usually I do:
        var hub = GlobalHost.ConnectionManager.GetHubContext<LiveHub>();
        hub.Clients.All.foo();
    }
}

here我读到:

OWIN集成中的常见错误是使用GlobalHost。在OWIN中,您可以从头开始创建配置。使用OWIN集成时,不应在任何地方引用GlobalHost。 Microsoft在此处提供了有关此和其他IoC集成问题的文档。

如果我不能使用“旧”方法,我该如何检索我的Hub?我试图在Erp中为LiveHub添加另一个DI,但它不起作用。在我的表单中,我创建了一个Erp实例:

public partial class Engine : Form
{
    private Erp _erp = new Erp();

    public Engine()
    {
        InitializeComponent();
    }
}

如果我添加DI声明是不可能的,因为我需要在构造函数中定义LiveHub,这需要自己的Erp参数...

我没看到什么?

c# dependency-injection signalr autofac
1个回答
2
投票

您可以通过发出事件将Hub与对象(在您的情况下为Erp)分离。

namespace MyProject.Hubs
{
    public class LiveHub : Hub
    {    
        public event Action SomethingHappened;

        public override Task OnConnected()
        {
            SomethingHappened?.Invoke();
            return base.OnConnected();
        }
    }
}

现在你可以连接Erp而Hub不必知道它。您必须在代码中的其他位置订阅该事件。但循环引用被打破了。

要将引擎与Form分离,您可以执行以下操作:

public partial class EngineForm : Form
{    
    public EngineForm()
    {
        InitializeComponent();
    }
}

public class Engine
{
    public Engine(EngineForm form, Erp erp)
    {
        this.form = form;
        this.erp = erp;
    }

    // Here is where you'll write some code to coordinate
    // communication between the Erp and the EngineForm. 
    //
    // The main advantage is that you can inject the Erp 
    // and have it preconfigured.
}
© www.soinside.com 2019 - 2024. All rights reserved.