1

Context: I am using the ServiceStack Framework (4.0.42) for my application. It is selfhosted and runs as a windows service. The main purpose is to give some devices the ability to communicate via web services (RESTful and ServerEvent).

For this I created a common interface for all types of devices which look like this (simplified):

public interface IDevice
{
    string GetName();        
    bool IsConnected(string id);
    event EventHandler<EventArgs> RaiseSomeEvent;
}

This interface is implemented in DLL’s one for each type of device.

My problem is that I can’t figure out how to forward the RaiseSomeEvent to notify a subscriber to ServerEvents. I tried many different implementations, none of them worked. Most, it ended up, that at runtime, when the DeviceAdapter_RaiseSomeEvent is called, the ServerEvents instance is null.

I am running out of ideas now.

Here is the actual (simplified) Version:

public class ServiceInterface : Service
{
    public IDevice DeviceAdapter { get; set; }         
    public IServerEvents ServerEvents { get; set; }
    public IAppSettings AppSettings { get; set; }

    public ServiceInterface(IDevice deviceAdapter)
    {
        DeviceAdapter = deviceAdapter;
        DeviceAdapter.RaiseSomeEvent += DeviceAdapter_RaiseSomeEvent;       
    }

    public void DeviceAdapter_RaiseSomeEvent(object sender, EventArgs e)
    {
        ServerEvents.NotifyAll("Something happend!");            
    }

and here the AppHost Class:

public class AppHost : AppSelfHostBase
{
    public IDevice DeviceAdapter;

    public AppHost()
        : base("grob.MachineConnector.Service", typeof(ServiceInterface).Assembly)
    { }

    public override void Configure(Funq.Container container)
    {            
        this.Plugins.Add(new ServerEventsFeature());

        switch (UsedAdapter)
        {
            case enAdapterTyp.DeviceTyp1:
                DeviceAdapter = new DeviceTyp1();
                break;
            case enAdapterTyp.DeviceTyp2:
                DeviceAdapter = new DeviceTyp2();

                break;
            default:
                throw new AdapterTypException("Wrong or no Adaptertyp is configured:" + UsedAdapter.ToString());
        }            
        container.Register(new ServiceInterface(DeviceAdapter));                       
    }       

Maybe it lies somewhere in the Funq. I am not sure what happening exactly with the DI, IoC, Autowiring stuff. I tried to write my own Plugin for the framework. I have no idea how to get the a valid instance of IServerEvents when a Event rises from my Device. Maybe I did some general design faults. For OOP and C# I am at beginner level.

Any hints are very welcome.

1 Answers1

2

The Service Dependencies are only available within the lifetime of a request, beyond that the Service and its dependencies are released/disposed. It's not clear from the event that it's only raised during the Request:

DeviceAdapter.RaiseSomeEvent += DeviceAdapter_RaiseSomeEvent; 

You should also never register a Service as they're automatically registered and autowired by ServiceStack:

 //Don't register Services
 //container.Register(new ServiceInterface(DeviceAdapter));         

Otherwise IServerEvents is just a normal Singleton dependency that's registered when the ServerEventsFeature Plugin is loaded.

Normally you'd just access it like any other dependency, where you'd just resolve it in the dependency that needs it, i.e:

container.Register<IDevice>(c => new DeviceTyp1 { 
    ServerEvents = c.Resolve<IServerEvents>()
});

Which will automatically inject the resolved IDevice into the Service dependencies:

public class ServiceInterface : Service
{
    public IDevice DeviceAdapter { get; set; }         

    public object Any(Request request)
    {
        //DeviceAdapter also has access to IServerEvents
        DeviceAdapter.Exec(request); 
    }
}

But if this event is not in reaction to a Service request then the event shouldn't be tied to a Service, i.e. you could just have the handler in the AppHost:

public override void Configure(Funq.Container container)
{            
    DeviceAdapter.RaiseSomeEvent += DeviceAdapter_RaiseSomeEvent;       
}

public void DeviceAdapter_RaiseSomeEvent(object sender, EventArgs e)
{
    var serverEvents = Container.Resolve<IServerEvents>();
    serverEvents.NotifyAll("cmd.Handler", "Something happend!");            
}

Please also see the documentation on Selectors so you know which selector the message should be sent with.

See this answer on different ways you can resolve IOC dependencies from outside of ServiceStack may also be helpful.

Community
  • 1
  • 1
mythz
  • 141,670
  • 29
  • 246
  • 390