myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Basistechnologien und allgemeine .NET-Klassen » Deklaration von Objekt innerhalb von Case
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Deklaration von Objekt innerhalb von Case

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
6274011253792 6274011253792 ist männlich
myCSharp.de-Mitglied

Dabei seit: 01.09.2018
Beiträge: 7


6274011253792 ist offline

Deklaration von Objekt innerhalb von Case

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo zusammen...

ich hab da ein Anfänger-Deklarationsproblem:


ich möchte ein Objekt einer bestimmten Klasse erstellen, wobei die Klasse abhängig von einem Parameter ist, welchen ich in irgendeiner Weise abfragen muss...


Konkret geht es um eine Outlook Nachrichtenklasse - ist aber IMHO auf jede andere Klasse / Objekttype zu übertragen. Problem ist hier, das ich 137 unterschiedliche Klassen behandeln muss... das bedeutet im Moment, das ich diesen Codeblock hier 137 mal brauche:

C#-Code:
switch(MessageClass)
{
   case "IPM.DOCUMENT":
     for (int retrytimes = 1;retrytimes <= 5;retrytimes++)
     {
        try
        {
           var Item = app.Session.OpenSharedItem(@TempFile) as Microsoft.Office.Interop.Outlook.DocumentItem;
           Item.Save();
           if (LogLevel > 1)
           {
              System.IO.File.AppendAllText(MSGLogfile, lt("Message created"));
           }
           Item.Move(objfolder);
           if (LogLevel > 1)
           {
              System.IO.File.AppendAllText(MSGLogfile, lt("Message stored in Folder"));
           }
           RestoreResult = 1;
           break;
        }
        catch (System.Exception ex)
        {
           System.IO.File.AppendAllText(logFileName, lt("Fehler: " + ex.Message));
        }
     }
     break;
[...weitere case's]
}

Statt dessen würde ich lieber sowas in der Art haben - die restliche Verarbeitung halt nur einmal unterhalb des Switch Blocks:

C#-Code:
var Item = null;
switch(MessageClass)
{
   case "IPM.DOCUMENT.ACROEXCH.DOCUMENT": Item=app.Session.OpenSharedItem(@TempFile) as Microsoft.Office.Interop.Outlook.DocumentItem; break;
   [...weitere case's]
}
for (int retrytimes = 1;retrytimes <= 5;retrytimes++)
{
   try
   {
      var Item = app.Session.OpenSharedItem(@TempFile) as Microsoft.Office.Interop.Outlook.DocumentItem;
      Item.Save();
      if (LogLevel > 1)
      {
         System.IO.File.AppendAllText(MSGLogfile, lt("Message created"));
      }
      Item.Move(objfolder);
      if (LogLevel > 1)
      {
         System.IO.File.AppendAllText(MSGLogfile, lt("Message stored in Folder"));
      }
      RestoreResult = 1;
   }
   catch (System.Exception ex)
   {
      System.IO.File.AppendAllText(logFileName, lt("Fehler: " + ex.Message));
   }
}

Aber das geht in der Art nicht, weil wenn Item nicht dediziert als app.Session.OpenSharedItem(@TempFile) as Microsoft.Office.Interop.Outlook.DocumentItem declariert ist, funktionier Item.Save() und Item.Move() entsprechend nicht mehr

So dass ich also oben einfach ein Konstrukt habe, das mir die 137 möglichkeiten durchgeht und ein entsprechendes Objekt vom richtigen Typen ausspuckt und ich die restliche verarbeitung dann einfach unten mache (alle anderen Schritte sind ja vollkommen identisch...)

Vermutlich total einfach, aber ich hab da irgendwie das Thema mit den deklarationen und Typen noch nicht so ganz verstanden... und mir fallen auch keine suchbegriffe mehr ein, die ich noch zu Dr. Google schicken könnte :-( Also sorry, wenn ich euch mit so einem Anfängerquatsch komme...

Vielen Dank
Liebe Grüße
Neuer Beitrag 01.09.2018 19:58 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Palladin007 Palladin007 ist männlich
myCSharp.de-Mitglied

avatar-4140.png


Dabei seit: 03.02.2012
Beiträge: 1.363
Entwicklungsumgebung: Visual Studio 2019
Herkunft: NRW


Palladin007 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Verstehe ich das richtig, dass die beiden Methoden Save und Move nur funktionieren, wenn die Variablen den tatsächlichen Typ des Objektes haben? Du darfst also nicht die Basis-Klasse verwenden als Variablen-Typ?
Klingt für mich nach einem groben OOP-Verbrechen ...

Wenn es so ist, wie ich denke, wirst Du nicht ohne Reflection weiter kommen:

C#-Code:
class Base
{
    public void DoSomething() => Console.WriteLine("Base");
}
class Child1 : Base
{
    public new void DoSomething() => Console.WriteLine("Child 1");
}
class Child2 : Base
{
    public new void DoSomething() => Console.WriteLine("Child 2");
}
class Program
{
    static void Main(string[] args)
    {
        Base child1 = new Child1();
        Base child2 = new Child2();

        child1.DoSomething(); // Base
        child2.DoSomething(); // Base

        DoSomething(child1); // Child 1
        DoSomething(child2); // Child 1

        Console.ReadKey();
    }

    static void DoSomething(Base item)
    {
        var method = item
            .GetType()
            .GetMethod(nameof(item.DoSomething));

        method.Invoke(item, null);
    }
}
Neuer Beitrag 01.09.2018 20:21 Beiträge des Benutzers | zu Buddylist hinzufügen
6274011253792 6274011253792 ist männlich
myCSharp.de-Mitglied

Dabei seit: 01.09.2018
Beiträge: 7

Themenstarter Thema begonnen von 6274011253792

6274011253792 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Palladin,

danke für Deine Antwort.

wenn ich das hier so mache

C#-Code:
object Item;
                                        switch ((string)dbReader[1].ToString().ToUpper())
                                        {
                                            case "IPM.DOCUMENT":
                                                Item = app.Session.OpenSharedItem(@TempFile) as Microsoft.Office.Interop.Outlook.DocumentItem;
                                                break;
                                            case "IPM.DOCUMENT.ACROEXCH.DOCUMENT":
                                                Item = app.Session.OpenSharedItem(@TempFile) as Microsoft.Office.Interop.Outlook.DocumentItem;
                                                break;
                                        }
                                        Item.Save();

erhalte ich im Save bereich die folgende Fehlermeldung:

"object" enthält keine Definition für "Save", und es konnte keine Save-Erweiterungsmethode gefunden werden, die ein erstes Argument vom Typ "object" akzeptiert (möglicherweise fehlt eine using-Direktive oder ein Assemblyverweis).

Mit Deinem Beispiel komme ich offen gestanden nicht ganz zurecht... da muss ich nochmal bissern nach Reflection googlen :-) Soweit bin ich noch nicht... Aber vielen Dank schon mal
Neuer Beitrag 01.09.2018 20:45 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Palladin007 Palladin007 ist männlich
myCSharp.de-Mitglied

avatar-4140.png


Dabei seit: 03.02.2012
Beiträge: 1.363
Entwicklungsumgebung: Visual Studio 2019
Herkunft: NRW


Palladin007 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Die Variable ist vom Typ object, das ändert die Situation natürlich.

Lies dir die Fehlermeldung mal genau durch und schau dir lieber die Grundlagen an, anstatt nach Reflection zu suchen. Hilfreich ist auch  dieses Buch, da wird das auch behandelt.

Das Problem kurz gefasst:
Der Compiler sucht die Methoden anhand des Typs der Variablen. Der Typ object hat einfach keine Save-Methode und da er nicht weiß, was irgendwann für ein Objekt in dieser Variable "stecken" könnte, kann er auch nicht wissen, dass es irgendwann eine Save-Methode geben wird.

Zu deinem switch:
Für mich sehen die Inhalte in den Cases alle gleich aus? Also warum ein Switch?
Und Du verwendest immer den Typ DocumentItem. Ist das immer dieser Typ? Dann kannst Du diesen Typ auch für die Variable verwenden, wenn nicht, musst Du schauen, ob eine Basis-Klasse oder ein Interface diese Save-Methode hat.


Wenn gar nichts hilft, tut's auch ene Generic-Lösung:

C#-Code:
T Save<T>(T item, Action<T> save)
{
    // ...
}

Item = Save(GetItem(), x => x.Save());

Wo ich das schreibe: Bei dem Problem, was ich zuerst vermutet habe, würde das auch helfen, da braucht's doch kein Reflection.
Neuer Beitrag 01.09.2018 21:21 Beiträge des Benutzers | zu Buddylist hinzufügen
6274011253792 6274011253792 ist männlich
myCSharp.de-Mitglied

Dabei seit: 01.09.2018
Beiträge: 7

Themenstarter Thema begonnen von 6274011253792

6274011253792 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Palladin,

das Object habe ich oben halt genommen, weil ich da ja noch nicht weiß, was es für ein Objekt wird.

das mit den identischen Cases war ein Copy&Paste fehler…

es sind natürlich unterschiedliche Typen - allerdings immer untertypen von Microsoft.Office.Interop.Outlook… also einmal ist es Noteobject, dann wieder Postobject oder einfach nur Mailitem…

Alle diese Typen haben .Save und .Move

Vielen Dank! Du hast mich da auf eine klasse Idee gebracht... ich mache einfach eine Funktion und übergebe aus der Case Anweisung das Objekt vom richtigen Typ...

Probier ich gleich mal

Danke Dir!
Liebe Grüße
Neuer Beitrag 01.09.2018 21:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Palladin007 Palladin007 ist männlich
myCSharp.de-Mitglied

avatar-4140.png


Dabei seit: 03.02.2012
Beiträge: 1.363
Entwicklungsumgebung: Visual Studio 2019
Herkunft: NRW


Palladin007 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wenn die Typen keine Basis haben, die die zwei Methoden definiert, reicht es nicht, das Objekt zu übergeben.
Du musst die zwei Methoden als Parameter an die Methode übergeben. Stichwort: Delegaten
Neuer Beitrag 01.09.2018 21:37 Beiträge des Benutzers | zu Buddylist hinzufügen
6274011253792 6274011253792 ist männlich
myCSharp.de-Mitglied

Dabei seit: 01.09.2018
Beiträge: 7

Themenstarter Thema begonnen von 6274011253792

6274011253792 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Müsste das nicht funktionieren:

C#-Code:
void Funktion(Parameter)
{
   Parameter.Save()
   Parameter.Move()
}

Main
{
switch(MESSAGECLASS)
case "IPM.POST":
   var ITEM= Microsoft.Office.Interop.Outlook.PostItem;
   Funktion(ITEM);
   Break;
case "IPM.NOTE":
   var ITEM= Microsoft.Office.Interop.Outlook.NoteItem;
   Funktion(ITEM);
   Break;
}
Neuer Beitrag 01.09.2018 21:44 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Palladin007 Palladin007 ist männlich
myCSharp.de-Mitglied

avatar-4140.png


Dabei seit: 03.02.2012
Beiträge: 1.363
Entwicklungsumgebung: Visual Studio 2019
Herkunft: NRW


Palladin007 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wie gesagt: Stichwort Delegaten :P
Hilfreich könnte auch das Stichwort "Lambda" sein.

Mein letzter Beispiel-Code von eben arbeitet so. Leicht angepasst:

C#-Code:
void Save<T>(T item, Action<T> save)
{
    save(item);
}

Save(Item, x => x.Save());
Neuer Beitrag 01.09.2018 22:20 Beiträge des Benutzers | zu Buddylist hinzufügen
6274011253792 6274011253792 ist männlich
myCSharp.de-Mitglied

Dabei seit: 01.09.2018
Beiträge: 7

Themenstarter Thema begonnen von 6274011253792

6274011253792 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

OK. Ich les mich da mal ein...

vielen herzlichen Dank!

Liebe Grüße und schönen Abend
Neuer Beitrag 01.09.2018 22:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.803
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

besonders für COM wurde in C# das Schlüssewort  dynamic eingeführt, s.a.  Verwenden des Typs dynamic.
Deklariere also einfach

C#-Code:
dynamic item;

und du kannst dann den Code aus deinem 2. Beitrag nutzen. ;-)
Falls die Methoden jedoch dann nicht existieren, erhältst du zur Laufzeit entsprechende Exceptions.
Neuer Beitrag 02.09.2018 10:18 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 2 Jahre.
Der letzte Beitrag ist älter als 2 Jahre.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 29.11.2020 11:32