Laden...

Dictionary<Type,MyClass<MyAbstract>> MyClass<MyConcret>-Values hinzufügen [wird gelöst mit C# 4.0]

Erstellt von LastGentleman vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.324 Views
LastGentleman Themenstarter:in
1.274 Beiträge seit 2005
vor 14 Jahren
Dictionary<Type,MyClass<MyAbstract>> MyClass<MyConcret>-Values hinzufügen [wird gelöst mit C# 4.0]

Hi Leute,

ich möchte mir ein kleines Konstrukt bauen, nur leider meckert der Complier dabei rum 😦

Ich möchte eine Liste von Objekten halten und wenn ein Typ reinkommt, dann soll er aus einem Dictionary eine Objekt sich holen.

Ganz einfach dachte ich mir.


 public Dictionary<Type, Buisness.MessageObjects.AbstractMessageBroker<AbstractMessage>> BrockerList

ganz einfach hinzufügen von meiner Abgeleiteten Klasse

 BrockerList.Add(typeof(Buisness.MessageObjects.TextMessage.TextMessage),
                new Buisness.MessageObjects.TextMessage.TextMessageBroker());

Die Klasse Textmessage Broker sieht so aus:


  public class TextMessageBroker  : AbstractMessageBroker<TextMessage>

Der Kompiler schreit hier mit

Error 3 The best overloaded method match for 'System.Collections.Generic.Dictionary <System.Type,Team.Buisness.MessageObjects.AbstractMessageBroker <Team.Buisness.MessageObjects.AbstractMessage>>.Add(System.Type, Team.Buisness.MessageObjects.AbstractMessageBroker <Team.Buisness.MessageObjects.AbstractMessage>)' has some invalid arguments C:\Daten\Projekte\SanSoft.Team.090525\Buisness\MessageHandlingLibary\MessageHandling.cs 22 13 MessageHandlingLibary

Error 4 Argument '2': cannot convert from 'Team.Buisness.MessageObjects.TextMessage.TextMessageBroker' to 'Team.Buisness.MessageObjects.AbstractMessageBroker <Team.Buisness.MessageObjects.AbstractMessage>' C:\Daten\Projekte\SanSoft.Team.090525\Buisness\MessageHandlingLibary\MessageHandling.cs 23 17 MessageHandlingLibary

Er ist doch die gleiche Klasse warum kann er das nicht konvertieren. Oder will er hier auch eine generische Schreibweise haben?

"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein

3.170 Beiträge seit 2006
vor 14 Jahren

Hallo,

hast Du mal versucht, das von Hand zu casten?

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

LastGentleman Themenstarter:in
1.274 Beiträge seit 2005
vor 14 Jahren

Danke Mark,

das wäre auch mein nächster Gedanke gewesen:

           BrockerList = new Dictionary<Type, Team.Business.MessageObjects.AbstractMessageBroker<AbstractMessage>>();
            Team.Business.MessageObjects.AbstractMessageBroker<AbstractMessage> newTextMessageBroker = 
                (Team.Business.MessageObjects.AbstractMessageBroker<AbstractMessage>) 
                new Business.MessageObjects.TextMessage.TextMessageBroker();

bekomme hier den Fehler

Error 1 Cannot convert type 'Team.Business.MessageObjects.TextMessage.TextMessageBroker' to 'Team.Business.MessageObjects.AbstractMessageBroker<Team.Business.MessageObjects.AbstractMessage>' C:\Daten\Projekte\Team.090525\Buisness\MessageHandlingLibary\MessageHandling.cs

"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein

3.170 Beiträge seit 2006
vor 14 Jahren

Hallo,

ich glaube so kannst Du das vergessen...
Der Kern des Problems läßt sich reduzieren auf:

  public abstract class AbstractType {}
  public class ImplementingType : AbstractType{}
  public class MyClass<T>{}

  public class Test
  {
    Test()
    {
      MyClass<ImplementingType> obj = new MyClass<ImplementingType>();
// der cast in der folgenden Zeile produziert bereits einen Fehler
      MyClass<AbstractType> abstractObj = (MyClass<AbstractType>)obj;
    }
  }

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

2.891 Beiträge seit 2004
vor 14 Jahren

Der Kern des Problems läßt sich reduzieren auf:

  
      MyClass<ImplementingType> obj = new MyClass<ImplementingType>();  
// der cast in der folgenden Zeile produziert bereits einen Fehler  
      MyClass<AbstractType> abstractObj = (MyClass<AbstractType>)obj;  
  

... womit wir wieder beim Thema sind, dass Ko- und Kontravarianz bei Generics momentan nicht geht. Kommt aber ab .NET 4.0.

Genauere Erklärung und eine Lösungsmöglichkeit gibt's u.a. in List<Unterklasse> auf List<Oberklasse> casten

Gruß,
dN!3L

LastGentleman Themenstarter:in
1.274 Beiträge seit 2005
vor 14 Jahren

Danke dN!3L,

hab dazu auch eine Presentation gefunden: http://startbigthinksmall.wordpress.com/2009/11/24/alles-vertragssache-ko-und-kontravarianz-in-c/

mein Problem ist damit nicht gelöst, muss schauen ob ich es irgendwie umgehen kann.

"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein

2.891 Beiträge seit 2004
vor 14 Jahren

mein Problem ist damit nicht gelöst, muss schauen ob ich es irgendwie umgehen kann.

Ja, hab mich auch schon öfter drüber geärgert.
Einzige Lösung ist momentan ein Konvertierung. In ReadOnlyBaseList <TBase, TDerived> - Ein hilfreicher Wrapper gibt's ja schon eine Möglichkeit für Listen, für Dictionaries geht z.B. folgendes:


Dictionary<string,FileStream> rawDictionary = new Dictionary<string,FileStream>();
Dictionary<string,Stream> pseudoCastedDict = rawDictionary.ToDictionary(kvp => kvp.Key,kvp => (Stream)kvp.Value);

Gruß,
dN!3L

F
10.010 Beiträge seit 2004
vor 14 Jahren

Nein, die vernünftige Lösung ist nicht mit einer abstrakten Klasse sondern einem Interface zu arbeiten.

2.891 Beiträge seit 2004
vor 14 Jahren

Nein, die vernünftige Lösung ist nicht mit einer abstrakten Klasse sondern einem Interface zu arbeiten.

Kann man dann aber genausowenig casten.
Die Lösung demnach also generell mit der Basisklasse/dem Interface arbeiten.

Gruß,
dN!3L

LastGentleman Themenstarter:in
1.274 Beiträge seit 2005
vor 14 Jahren

Danke für eure Ratschläge, hab das ganze mal ohne Generischen Rückgabewert gemacht, die Liste hält jetzt Objekte. Brauche leider einen Cast dafür. 😦

 
   public class MessageHandling
    {
        public Dictionary<Type, object> BrockerList
        {
            get;
            set;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:MessageHandling"/> class.
        /// </summary>
        public MessageHandling()
        {
            BrockerList = new Dictionary<Type, object>();

            Team.Business.MessageObjects.IAbstractMessageBroker<TextMessage> newTextMessageBroker =
                    new Business.MessageObjects.TextMessage.TextMessageBroker();

            BrockerList.Add(typeof(Business.MessageObjects.TextMessage.TextMessage),
                newTextMessageBroker);
        }

        public Team.Business.MessageObjects.AbstractMessageBroker<IAbstractMessage> GetBrockerForType(Type messageType)
        {
            Team.Business.MessageObjects.AbstractMessageBroker<IAbstractMessage> ob =
                (Team.Business.MessageObjects.AbstractMessageBroker<IAbstractMessage>)
                BrockerList[messageType];
            return ob;
        }
    }

EDIT:
So der Compiler beschwert sich nicht mehr. Nur noch bei der Ausführung 😦

"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein