DCM Best Practice für den Context

Arne Drews

Mitglied
Moin,

Aus aktuellem Anlass möchte ich gerne mal fragen, was so best practice im Bezug auf den Context einer DCM ist, bzw. wie ihr das macht.

Ich habe bisher immer eine Vorlage von mir verwendet, die für meine Zwecke immer gut funktioniert hat:
C#:
public class _Vorlage : IDcmCallback
{
    Mandant _Mandant;
    Beleg _Beleg;

    bool _IstInitial;



    public bool Entry(IDcmContext context)
    {
        InitializeObjects(context);

        if (_Mandant == null || _Beleg == null)
            return true;

        // Nur bei Initialspeicherung des Belegs?
        if (!_IstInitial)
            return true;


        /*
            ...some code here
        */


        // Ende der DCM
        return true;
    }


    /*
        BelegUndMandantAusContext(IDcmContext) : weist den globalen Objekten _Beleg und _Mandant die Objekte aus dem context zu.
     */
    private void InitializeObjects(IDcmContext context)
    {
        // Context finden (kann beliebig erweitert werden)
        switch (context.ListId)
        {
            case DcmDefinitionManager.DcmListId.VKBelegBeforeSave:
                _Mandant = (context as DcmContextBelegBeforeSave).Mandant;
                _Beleg = (context as DcmContextBelegBeforeSave).Beleg;
                break;

            case DcmDefinitionManager.DcmListId.VKBelegProxyBeforeSave:
                _Mandant = (context as DcmContextBelegProxyBeforeSave).Mandant;
                _Beleg = (context as DcmContextBelegProxyBeforeSave).Beleg;
                break;

            /*
                ...und weitere...
            */

            default:
                return;
        }

        if (_Beleg != null)
            _IstInitial = IstInitialAnlage();
    }


    /*
        IstInitialAnlage() : liefert true oder false, basierend auf dem Speicherstatus des Belegs.
     */
    private bool IstInitialAnlage(bool strict = false)
    {
        return _Beleg.Speicherstatus == BelegSpeicherstatus.NeuerBeleg
            && (strict ? _Beleg.Speichermode == BelegSpeicherstatus.NeuerBeleg : true);
    }
}

Wie man daran sehen kann, setze ich eine globale Variable _Mandant und _Beleg und weise diese dem aufgerufenen Context entsprechend zu.
Das hat bisher auch immer sehr gut funktioniert, weil ich den Speichervorgang im Grunde nie abbreche, sondern nur Änderungen am Beleg im Bedarfsfall vornehme.

Nun hatte ich aber den Fall, dass ich unter bestimmten Kriterien das Speichern des Belegs unterbinden muss, was ich allerdings über den Context machen muss. Das habe ich zum Anlass genommen, meine Vorlage noch mal zu überarbeiten:
C#:
public class _VorlageNEU : IDcmCallback
{
    dynamic _Context;

    Mandant _Mandant;
    Beleg _Beleg;

    bool _IstInitial;



    public bool Entry(IDcmContext context)
    {
        InitializeContext(context);

        // Mandant oder Beleg nicht zugewiesen => Ende der Dcm
        if (!InitializeObjectsByContext())
            return true;

        // Nur bei Initialspeicherung des Belegs? Wenn kein Initialbeleg => Ende der Dcm
        if (!_IstInitial)
            return true;


        /*
            ...some code here
        */


        // Ende der DCM
        return true;
    }


    /*
        BelegUndMandantAusContext(IDcmContext) : weist den globalen Objekten _Beleg und _Mandant die Objekte aus dem context zu.
     */
    private void InitializeContext(IDcmContext context)
    {
        // Context finden (kann beliebig erweitert werden)
        switch (context.ListId)
        {
            // VK Events
            case DcmDefinitionManager.DcmListId.VKBelegBeforeSave:
                _Context = context as DcmContextBelegBeforeSave;
                break;

            case DcmDefinitionManager.DcmListId.VKBelegProxyBeforeSave:
                _Context = context as DcmContextBelegProxyBeforeSave;
                break;

            /*
                ...und weitere...
            */

            // EK Events
            case DcmDefinitionManager.DcmListId.EKBelegProxyBeforeSave:
                _Context = context as DcmContextBelegProxyBeforeSave;
                break;

            case DcmDefinitionManager.DcmListId.EKBelegProxyAfterSave:
                _Context = context as DcmContextBelegProxyAfterSave;
                break;

            /*
                ...und weitere...
            */

            default:
                return;
        }
    }


    private bool InitializeObjectsByContext(bool strict = false)
    {
        if (_Context == null)
            return false;

        _Mandant = _Context.Mandant;
        _Beleg = _Context.Beleg;

        if (_Mandant == null || _Beleg == null)
            return false;

        _IstInitial = _Beleg.Speicherstatus == BelegSpeicherstatus.NeuerBeleg
            && (strict ? _Beleg.Speichermode == BelegSpeicherstatus.NeuerBeleg : true);

        return true;
    }
}
Ich verwende dynamic i.d.R. eher nicht, aber hielt es für diesen Fall für hilfreich.
In dieser Vorlage weise ich nur _Context entsprechend dem übergebenen Context zu und intialisiere meine Objeke _Mandant und _Beleg auf Basis dieses dynamic-Objektes.

Warum mache ich das?
Der Context einer DCM wird vermutlich in vielen Fällen immer die gleichen Parameter und Eigenschaften zur Verfügung stellen. Zumindest im Bereich der Belege-DCMs kann ich mir das sehr gut vorstellen. Meine Idee war aber, dass es evtl. doch mal abweichende Eigenschaften gibt für die die Art des Context wichtig ist. Ich bin in solchen Vorlagen gerne so flexibel und skalierbar wie möglich, daher dieser Gedanke.

Ich habe die Vorlage gestern Abend mal so grob getestet und es scheint zu funktionieren.
Mich interessiert nun, ob ihr das für sinnvoll haltet oder wie ihr mit dem Context umgeht?

Danke für Tipps und Anregungen.
 
Moin,

ich mache es zumeist nach folgendem Schema weil ich dies am übersichtlichsten finde.
In der Entry-Methode nur je eine private prozedur aufrufen und dieser den typisierten Context übergeben.

Beispiel:
Code:
        public bool Entry(IDcmContext context)
        {
            try
            {
                switch (context.ListId)
                {
                    case DcmDefinitionManager.DcmListId.VKBelegProxyAfterSetKonto:
                        _VKBelegProxyAfterSetKonto((DcmContextBelegProxyAfterSetKonto)context);
                        break;
                    case DcmDefinitionManager.DcmListId.VKBelegPositionProxyAddArtikelposition:
                        _VKBelegPositionProxyAddArtikelposition((DcmContextBelegPositionProxyAddArtikelposition)context);
                        break;

                    case DcmDefinitionManager.DcmListId.FertigungsauftragAfterSave:
                        _FertigungsauftragAfterSave((Sagede.OfficeLine.Pps.Fertigungsauftrag.DcmContextSave)context);
                        break;

                    default:
                        break;
                }
                return true;
            }
            catch (Exception ex)
            {
                TraceLog.LogException(ex);
                return false;
            }
}


Und dann die jeweiligen Prozeduren mit dem typisierten Context:

Code:
        private void _VKBelegProxyAfterSetKonto(DcmContextBelegProxyAfterSetKonto context)
        {
            if (SageTools.MandantRelevant(context.Mandant))
                VKBelegHelper.AfterSetKonto(context.Mandant, context.Beleg);
        }

        private void _VKBelegPositionProxyAddArtikelposition(DcmContextBelegPositionProxyAddArtikelposition context)
        {
            if (SageTools.MandantRelevant(context.Mandant))
                VKBelegHelper.CheckPositionSteuerklasse(context.Beleg, context.Position);
        }
 
Zurück
Oben