Laden...

WCF-Service, Windows-Service und klassenübergreifender Zugriff auf Objekte

Erstellt von Igotcha vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.628 Views
I
Igotcha Themenstarter:in
4 Beiträge seit 2007
vor 5 Jahren
WCF-Service, Windows-Service und klassenübergreifender Zugriff auf Objekte

Hallo zusammen,

ich erstelle einen WCF-Service, mit dem verschiedene "Activities" (langlaufende Tasks) erstellt und auf dem Server parallel ausgeführt werden. Das funktioniert auch alles grundsätzlich, aber meine Bemühungen des Decouplings führen jetzt zu einem Problem im Zusammenspiel der folgenden Komponenten:
1.Servicehost: Konsolenanwendung, die den WCF-Service wahlweise direkt ausführt oder als Windows-Service (ServiceBase) installierbar ist. 1.WCF-Serviceklasse: Die Implementierung des Service-Interfaces aus 4. 1.Factory-Klassen: Factories zum Erstellen von Activities, Logs, etc. Wird in 2. genutzt 1.weitere Klassenbibliothek (Interfaces, etc.)

In der Serviceklasse (2.) sieht das zum Beispiel so aus:

public class AutomationService : IAutomationService
    {
        static FactoryActivity factoryActivity = new FactoryActivity();
        static FactoryLogging factoryLogging = new FactoryLogging();     

        public ResultObject CreateActivity(Activity activity, string Name, string Configuration)
        {
            ResultObject resultObject = new ResultObject();
            IActivity _activity = null;

            try
            {
                switch (activity)
                {
                    case Activity.TestActivity:
                        _activity = factoryActivity.Create(Activity.TestActivity, Name, Configuration);
                        _activity.Start();
                        break;               
                }
                                

                resultObject.Status = ResultStatus.OK;
                resultObject.StatusMessage = $"Activity {_activity.Name} Created.";
                return resultObject;
            }
            catch (Exception ex)
            {
                factoryLogging.Log(LogLevel.Error, $"CreateActivity::Activity={activity}::ERROR::{ex.Message.ToString()}");

                resultObject.Status = ResultStatus.ERROR;
                resultObject.StatusMessage = $"Activity Creation {Name} - An Error Occured";
                return resultObject;
            }                           
        }
        // Weitere Service-Funktionen

In der FactoryActivity sieht das so aus:

public class FactoryActivity
    {
        FactoryLogging factoryLogging = new FactoryLogging();

        readonly Dictionary<Guid, IActivity> dictActivities = new Dictionary<Guid, IActivity>();

        public IActivity Create(Activity activity, string Name, string Configuration)
        {
            // Create Actvity from Factory, based on the selected Activity
            switch (activity)
            {
                case Activity.TestActivity:
                    TestActivity _activity = new TestActivity(Name, Configuration);
                    _activity.OnLogStatus += factoryLogging.OnLogStatus;

                    // Save Activity config to Database
                    _activity.Save();

                    // Add Activity to dictionary
                    dictActivities.Add(_activity.Guid, _activity);

                    factoryLogging.Log(LogLevel.Info, $"{_activity.Guid}|{_activity.GetType().Name.ToString()}|{_activity.Name} created.");
                    return _activity;    
                // Weitere Activities
                // ...                
                default:
                    return null;               
            }
        }

Aktuell hänge ich daran, dass ich aus dem Servicehost heraus keine Möglichkeit finde auf die FactoryActivity, speziell auf das dictActivities (statisch, darf nur einmal vorhanden sein), zuzugreifen. Ich möchte nämlich beim "OnStop" des Windows Services prüfen, ob noch Activities laufen und diese dann über eine Funktion "StopAllActivities" der FactoryActivity stoppen. Ich kann aber aus der Dienst-Klasse nicht auf das statische FactoryActivity der Service-Klasse zugreifen.

Auch sehe ich momentan keine Möglichkeit, eine statische FactoryActivity in der Dienst-Klasse zu erstellen und dieses an die Service-Klasse zu übergeben, da die Erstellung des Servicehosts keine Parameter akzeptiert:

host = new ServiceHost(typeof(AutomationService), baseAddress);

Wäre für eine Anregung sehr dankbar.

16.842 Beiträge seit 2008
vor 5 Jahren

Ist das nun eine Frage, wie man das allgemein angeht, oder wie man das angeht, wie Du es machst?

Ich würde nämlich an Deiner Stelle die gesamte Konstellation infrage stellen: inklusive WCF und Co.
WCF gilt in dieser Form als obsolete und hinkt 1-2 Generationen bereits hinterher.

Das, was Du da baust, gibt es bereits fertig, Open Source, extrem stabil (nutze ich in vielen Projekten), skalierbar und reliable: Hangfire.

Der statische Ansatz wird ohnehin weh tun; macht es so auch nicht testbar.
Wenn Du es so machen willst - das empfehle ich wirklich nicht, nimm Hangfire in einer ASP.NET Runtime (kann auch als Service laufen und als Konsole!) - dann verwende Dependency Injection und hol Dir zur Not über den Service Locator Pattern die jeweilige Instanz Deines der Activities.

I
Igotcha Themenstarter:in
4 Beiträge seit 2007
vor 5 Jahren

Hangfire sieht interessant aus, schaue ich mir garantiert an. Wenn Du von veralteten Techniken sprichst, was würdest Du denn im Kontext von Hangfire empfehlen? Aktuell entwickle ich ausschließlich WinForms-Anwendungen (lokale Desktop-Anwendungen). Im webbasierten Bereich wäre ich offen für Vorschläge.

Zu meiner ursprünglichen Frage: Es handelt sich um eine grundsätzliche Frage, daher habe ich dies auch in Basistechnologien gepostet. Was wäre denn der klassische Ansatz, um das Problem anzugehen?

3.003 Beiträge seit 2006
vor 5 Jahren

"veraltet" ist in diesem Zusammenhang extrem subjektiv. Abt sieht das so, das heisst aber nicht, dass es objektiv so ist. Könnte man streiten, hat man auch schon und führt zu nix.

Dein Problem ist ein konzeptionelles, mit einer anderen Technologie kannst du es umgehen, aber nicht lösen. Stell dir ein paar Fragen:

  • sollte Servicehost als Container für die gehosteten services (sic!) wissen, was die Services tun?
  • welche Möglichkeiten haben Services, außer über eine statische Klasse Informationen miteinander zu teilen? (Hint: dieselben wie jedes andere Objekt auch.)
  • Gibt es möglicherweise Konzepte, die die Erstellung, Zerstörung und Verwaltung von Objekten organisieren?

Wir machen etwas ganz ähnliches in einem Kontext, der (aus unserer Sicht) die Benutzung von WCF erzwingt. Es ist durchaus konkurrenzfähig. Das heisst wäre es, wenn es nicht das einzige zuverlässig funktionierende Produkt auf dem Markt wäre. Und es gab durchaus Versuche durch die Mitbewerber.

LaTino
Edit: noch ein bisschen Lesestoff (es gibt mehrere Ansätze, wie man das Problem lösen könnte. Die Links gehören nicht notwendigerweise zum selben, aber ich halte sie für generell hilfreich für dich):
https://docs.microsoft.com/de-de/dotnet/framework/wcf/extending/extending-hosting-using-servicehostfactory
https://blogs.msdn.microsoft.com/carlosfigueira/2011/06/13/wcf-extensibility-servicehostfactory/
http://scotthannen.org/blog/2016/04/13/wcf-dependency-injection-in-5-minutes.html
https://lostechies.com/jimmybogard/2008/07/30/integrating-structuremap-with-wcf/
(das blog ist generell lesenswert)
...und und und.

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

16.842 Beiträge seit 2008
vor 5 Jahren

"veraltet" ist in diesem Zusammenhang extrem subjektiv. Abt sieht das so, das heisst aber nicht, dass es objektiv so ist.

Nein, das sieht nicht nur Abt so, daher hat Abt auch geschrieben: WCF gilt in dieser Form als obsolete.
Und ja, in dieser Form ist es veraltet.

Es gibt WCF Aspekte, die sind noch aktuell - keine Frage - in 99% der Fälle gibt es eben modernere Lösungen.
Dazu gibt es auch auf GitHub eine von Microsoft sehr offene Kommunikation, wieso WCF so in der Form nicht auf .NET Core kommt.

3.003 Beiträge seit 2006
vor 5 Jahren

Merkste selber? Dein Argument beschränkt sich darauf, dass du sagst, dass es so ist.
Müssen wir nicht diskutieren.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

16.842 Beiträge seit 2008
vor 5 Jahren

So werden Tatsachen und Fakten, die jeder frei einsehen kann und nichts mit meiner Meinung zutun haben, natürlich schnell ignoriert.
Sauber 😃