OPCFoundation / UA-.NETStandard

OPC Unified Architecture .NET Standard
Other
1.96k stars 946 forks source link

Sub-classing of Subscription is not supported on reconnect #2096

Closed htbmw closed 11 months ago

htbmw commented 1 year ago

Type of issue

Current Behavior

In order to implement a mechanism for creating and managing subscriptions with triggering monitored items, I inherit from the Subscription class to create my own sub-class, say SubscriptionWithTriggeringItems.

I then add instances of this sub-class to the Session.Subscriptions collection and everything works as expected. But when the reconnect feature kicks in and reconnects the session after the client and server have been disconnected, then the original sub-class instances are replaced with instances of the original base type Subscription. This means any extended behavior and features of the sub-class are lost.

Digging into the libraries, I could see there is a lot of recreation of sessions and subscriptions happening behind the scenes during a reconnect. It became clear that because of the recreate logic, the libraries only knows about the Subscription class and nothing about external user-defined sub-classes.

This brings me to the question if it would be possible to allow for injection of factories that would allow instances of custom user-defined sub-classes to be created during the reconnect cycle?

Expected Behavior

Be able to extend the existing behavior of the Subscription class by creating a sub-class and have it correctly restored / recreated upon reconnection of a disconnected session. By injecting a factory the underlying libraries / SDK don't need to understand how to instantiate user-defined types.

Steps To Reproduce

1) Create sub-class of Subscription 2) Create instance of sub-class 3) Add instance to Session.Subscriptions as one would with a normal subscription 4) Observe normal functioning under normal operation with a connected client and server 5) Restart the server to force a reconnect cycle 6) When session reconnected, observe that instances of the sub-class on the Session.Subscriptions collection have been replaced by instances of the base Subscription class.

Environment

- OS: Windows 10, Ubuntu
- Environment: Visual Studio 2022
- Runtime: .Net 6
- Nuget Version: Any
- Component: Opc.Ua.Client
- Server: Reference Server
- Client: Own developed client

Anything else?

At the moment I have to redesign and build an external management to accommodate something that would have been much easier, quicker and cleaner with sub-classing

mregen commented 1 year ago

We should add the factory support or a similar mechanism. Thanks for the feedback!

htbmw commented 1 year ago

That will be awesome!

Currently I am using a workaround by storing state in the Handle property of subscriptions and monitored items, and the handle is transferred fine when new subscriptions and monitored items are created internally.

It is unfortunately not a very clean approach, but the factory should solve that.

mregen commented 11 months ago

Hi @htbmw, I am looking into adding an extra clone that allows to override internal clone of session, subscription and monitored item by providing a virtual function that needs implementation if you use subclassing. Its used in the reconnect case.

        /// <summary>
        /// Clones a subscription or a subclass with an option to copy event handlers.
        /// </summary>
        /// <returns>A cloned instance of the subscription or its derivative.</returns>
        public virtual Subscription SubscriptionClone(bool copyEventHandlers)
        {
            return new Subscription(this, copyEventHandlers);
        }

Would it work for you? Similar approach for Session and MonitoredItems.

htbmw commented 11 months ago

Hi @mregen ,

I think that can work yes, but will have to try it out first. Could you do it on a branch that I can pull and play around with in order to provide more constructive feedback?

Thanks for the follow up and giving this a try.