Um in unserer Software DependencyInjection zu ermöglichen, gibt es bei uns eine Systematik namens DynamicLogic.
Diese Systematik beruht auf dem ServiceLocatorPattern welches über die SOGObjectFactory implementiert wurde.
DynamicLogic basiert auf Interfaces sodass die Verwendung in jeder Assembly möglich ist, ohne dabei Abhängigkeiten zu erzeugen. Somit ist es möglich, ein Interface IPreisKalkulation zentral in ERP.Base oder Entity zu definieren, aber erst im Modul Preise dies tatsächlich zu implementieren. Trotzdem lässt sich dann diese Logik in alllen Modulen verwenden.
Um ein solche Logik zu instanzieren muss das jeweilige Interface als Schlüssel an die Objectfactory übergeben werden:
IPreisKalkulation kalkulation = SOGObjectFactory.CreateDynamicLogic<IPreisKalkulation>();
Das Interface muss dazu um die Information erweitert werden, wo diese konkrete Klasse liegt
[DynamicLogicLoad(ERPAssemblies.ASM_PREISE, "SOG.ERP.Modules.Preise.PreisKalkulation")]
public interface IPreisKalkulation : IDynamicLogic { ... }
Neben der "normalen" DynamicLogic gibt es zusätzlich das Interface ICachedDynamicLogic. Dies hat den Unterschied, das Instanzen gecached werden und nicht bei jedem Aufruf erzeugt werden.
Klassen die so funktionieren sollen, müssen also das Interface ICachedDynamicLogic implementieren und zusätzlich über das DynamicLogicLoadAttribut eine LifeTime definieren.
Somit können diese Logiken dann selbst Ergebisse zwischenspeichern um diese nicht jedesmal neu berechnen zu müssen.
ISOGUniversalSendKeysHandler handler = SOGObjectFactory.GetCurrentDynamicLogic<ISOGUniversalSendKeysHandler>();
[DynamicLogicLoad(ERPAssemblies.ASM_ARTIKEL, "SOG.ERP.Modules.Artikel.Logik.ArtikelanwahlFactory", DynamicLogicLifeTime.Session)]
public interface IArtikelanwahlFactory : ICachedDynamicLogic {...}
Solche Klassen müssen Threadsicher sein. Das heisst unter anderem auch zustandslos bzw. funktional.
Um in Kundenprojekten eine individuelle Ableitung zu erzeugen die dann überall verwendet wird, ist die Angabe des SOGConfigurationTypeAttribute notwendig.
Dieses definiert, welcher Schlüssel ersetzt wird. Alles andere passiert dann automatisch beim Laden der Script.dll. Als Schlüssel dient bei DynamicLogic immer das interface.
Eine Ableitung muss nicht die ursprüngliche Implementierung ableiten, es ist nur erforderlich, das entsprechende Interface zu implementieren. Somit sind folgende Beispiele zulässig:
[SOGConfigurationType(typeof(IPreisKalkulation))]
public ProjPreisKalkulation : IPreisKalkulation { ... }
[SOGConfigurationType(typeof(IPreisKalkulation))]
public ProjPreisKalkulation : ERPPreisKalkulation { ... }
z.B. In den Funktionen "_setupDependencies" werden außerdem Typersetzungen durchgeführt, um z.B. WPF-Spezifische Einstellungen vorzunehmen.
DependencyManager.Current.ReplaceDependencyType<IhhpxMask, hhpxWpfMask>();