Raise a Fluxor Action within a regular class within a .cs file

Viewed 832

Can someone who is either familiar with Fluxor or C# Dependency Injection help me with an issue that I've struggled with for several days please.

When you use Fluxor within a Blazor Component you include the following to raise an Action:

@Inherits Blazor.Fluxor.Components.FluxorComponent
@Inject IDisptacher dispatcher

That allows you to raise an Action within the Component with: Dispatcher.Dispatch(new MyAction(MyParameter));

In addition to dispatching Fluxor Actions from a Blazor Component (which I have working well), I need to be able to dispatch an Action from a regular class in a .cs file. I've tried Injection as shown in the following TestClass but a NullReferenceException is raised when Dispatcher.Dispatch is hit.

using Fluxor;
using Microsoft.AspNetCore.Components;

namespace ICET.Store
{
    public class TestClass
    {
        [Inject]
        private IDispatcher Dispatcher { get; set; }

        public void onMessage()
        {
            // Other code removed
            Dispatcher.Dispatch(new LoggedInAction(phoneNumber));
        }
    }
}

Clearly something has to instantiate the Dispatcher declared with private IDispatcher Dispatcher { get; set; } but I thought that instantiation happened in the Startup.cs with the following:

services.AddFluxor(options =>
{
   options.UseDependencyInjection(typeof(Startup).Assembly)
{);

Clearly I missing something here but I'm stumped with what that is. Can someone give me some guidance about how a Fluxor Action can be raised within a Class included in a regular .cs file. Thanks.

Using Constructor Injection as suggested by Peter Morris I've altered my Test Class to:

public class TestClass
    {
        IDispatcher _dispatcher;

        public TestClass(IDispatcher dispatcher)
        {
            _dispatcher = dispatcher;    
        }
    
        public void onMessage()
        {
            // Other code removed

            _dispatcher.Dispatch(new LoggedInAction());
        }
    }

However, what I'm struggling with now is when I instantiate my Class how do I get a reference to a Fluxor Disptacher that I can pass to the TestClass Constructor? I thought as Fluxor is implemented as a Service ie;

services.AddFluxor(options =>
{
   options.UseDependencyInjection(typeof(Startup).Assembly)
{);

... that's it somehow available globally to reference.

Next update ...

My TestClass has been altered to implement an Interface and is now registered as a Scoped Service in Startup.cs

public interface ITestClass
    {
        public void InitiateAction();

    }


    public class TestClass : ITestClass
    {
        IDispatcher _dispatcher;

        public TestClass(IDispatcher dispatcher)
        {
            _dispatcher = dispatcher;
        }

        public void InitiateAction()
        {
            _dispatcher.Dispatch(new LoggedInAction("123456"));
        }
    }

Startup.cs

services.AddScoped<ITestClass, TestClass>();

As a result of these changes I was expecting the TestClass would have been instantiated and I'd be able to call its InitiateActionmethod to Dispatch an Action. However, it remains stubbornly null in the following code:

class DeviceListener : Cometd.Bayeux.Client.IMessageListener
    {
        private readonly IDispatcher _dispatcher;
        private ITestClass _testClass;

       public void onMessage(Cometd.Bayeux.Client.IClientSessionChannel mChannel, Cometd.Bayeux.IMessage message)
        {
            _testClass.InitiateAction();
}

Update ... My DeviceListener class implements the Cometd.Bayeux.Client.IMessageListener interface and defines a Callback which is executed when an unsolicited message is received from a server process. It's referenced in Startup.cs:

listener = mClient.getChannel("/v2/me/devices");
listener.subscribe(new GWS.DeviceListener());

The class is structured as follows:

    class DeviceListener : Cometd.Bayeux.Client.IMessageListener
    
        {
            private readonly IDispatcher _dispatcher;
    
            public DeviceListener(IDispatcher dispatcher)
        {
            _dispatcher = dispatcher;
        }

public void onMessage(Cometd.Bayeux.Client.IClientSessionChannel mChannel, Cometd.Bayeux.IMessage message)
            {
                _dispatcher.Dispatch(new LoggedInAction("12345");
    
            }
        }

All illustrated in the above DeviceListener, I want to be able to dispatch a Fluxor Action from within onMessage.

The above DeviceListener shows a parameterized Constructor but that actually causes an argument compile error against listener.subscribe(new GWS.DeviceListener()); in Startup.cs

1 Answers

In a non component use constructor injection.

The problem is probably that your object isn't being created by the dependency container, so no code is fixing up the [Inject]

Related