wie Template mit 2 dynamischen Typen als Parameter erstellen



  • Hi,

    ich hab ein paar Interfaces und Klassen:

    public interface InterfaceA {}
    public interface InterfaceB {}
    
    public class SomeClass<A, B> : where A : InterfaceA, where B : InterfaceB
    { 
       public A ObjectA { get; set; }
       public B AbjectB { get; set; }
    }
    

    Mein Problem ist, ich kann keine Instanz von SomeClass erstellen, da mir ich die tatsaechlichen Laufzeit-Typen von A und B nicht kenne - aber die brauche ich (siehe unten).

    Haette SomeClass nur einen Template-Parameter, waere es kein Problem, Objekte
    von SomeClass wuerden z. B. mithilfe vom Factory-Pattern instantiiert.

    Nun stosse ich wieder auf das gleiche Problem, dass ich seit Jahren bei der
    Programmierung wiederfinde: ich weiss zur Laufzeit nicht, was die Laufzeit-Typen von den beiden Parametern A und B sind, ohne Spaghetti-Code zu schreiben.

    Gibt es fuer dieses Problem evtl. auch ein Pattern? Ich hab solche Situationen:

    InterfaceA a = new TypeA();
    InterfaceB b = new TypeB();
    
    SomeClass<TypeA, TypeB> sc = new SomeClass<TypeA, TypeB>();
    sc.ObjectA = a;
    sc.ObjectB = b;
    

    Das Problem der ganzen Sache ist, dass die Objekte 'a' und 'b' ganz wo anders erstellt werden (auf einer Client-Anwendung erstellt, an die Server-Anwendung uebergeben).

    Was mir bleibt, ist der statische Type von a und b, sprich InterfaceA und InterfaceB. Die tatsaechlichen Typen sind mir voellig unbekannt.
    Leider kann InterfaceX nicht als Template-Parameter an SomeClass uebergeben - SomeClass ist eine System.Configuration.ConfigurationSection. Und weil es eine ConfigurationSection ist, braucht es die tatsaechlichen Typen von 'a' und 'b' um sie anstaendig (de)serialisieren zu koennen. Dies geht mit blossen Interfaces leider nicht.

    Wie gefragt, gibt es fuer diese problematik vielleicht ein Muster?
    😕



  • Äh.
    Pack die Funktionen die du zum "anstaendig (De)serialisieren" brauchst doch mit in das Interface?!?

    Ich sehe grad das Problem überhaupt nicht...

    Kannst du das Beispiel vielleicht etwas konkreter machen?



  • Ja gern. Worauf es hinauslaufen soll, ist das:

    public class MyConfigurationSection : System.Configruation.ConfigurationSection
    {
        [ConfigurationProperty("Etwas")]
        public BaseClass Instance
        {
            get { return (BaseClass)this["Etwas"]; } 
            set { this["Etwas"] = value; }
        }
    
        [ConfigurationProperty("NochEtwas")]
        public BaseClass NochEtwas
        {
            get { return (BaseClass)this["NochEtwas"]; } 
            set { this["NochEtwas"] = value; }
        }
    }
    

    Das ist meine Kanfigurations-Klasse. Ich moechte jeden beliebigen Typ, der von BaseClass ableitet,
    in 'Instance' speichert koennen, anschliessend wird die MyConfigurationSection-Klasse in der
    App.config gespeichert.

    Problem:
    - Wenn BaseClass ein Interface oder eine abstrakte Klasse ist, kann die Section nicht gespeichert
    werden. Fehlermeldung:

    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.MissingMethodException: Cannot create an abstract class.

    - Da mir der Laufzeit-Typ von Instance nie bekannt ist (sie leiten sich jedoch alle von BaseClass ab), habe
    ich diesen Anzatz mit BaseClass als Property-Typ gewaehlt. Der System.Configuration Namensraum von MS scheitert
    jedoch schon an so einem grundlegenden Konzept wie der "Generalisierung".

    Nun habe ich den Anzatz im ersten Post als 'Workaround' gewaehlt, weil System.Configuration gluecklicherweise noch in der Lage ist, Template-Parameter mit in der App.config zu speichern. Diese Template-Parameter koennen dann den Laufzeit-Typ von 'Insance' und anderen Properties in der 'MyConfigurationSection' angeben. Warum es noch nicht funktioniert, ist oben beschrieben.



  • hustbaer schrieb:

    Äh.
    Pack die Funktionen die du zum "anstaendig (De)serialisieren" brauchst doch mit in das Interface?!?

    Ich (de)serialisiere nicht selbs. Das macht System.Configuration fuer mich:
    http://www.codeproject.com/KB/dotnet/mysteriesofconfiguration.aspx



  • Dann wirst du vermutlich wohl selbst serialisiern müssen, oder zumindest selbst in die Serialisierung eingreifen.

    Und bitte: schreib nicht "Templates" wenn du "Generics" meinst.



  • hustbaer schrieb:

    Und bitte: schreib nicht "Templates" wenn du "Generics" meinst.

    Du musst das Wort Template nicht von C++ & Sonstigem abhaengig machen. Ich weiss die Unterschiede; bei Template denk ich lediglich an das Wort 'Vorlage', was Generics lezten Endes auch sind.

    Dann wirst du vermutlich wohl selbst serialisiern müssen, oder zumindest selbst in die Serialisierung eingreifen.

    Dass eine ConfigurationSection den System.Type nicht fuer ihre ConfigurationElement-Properties mitspeichert, ist eine Katastrophe.

    Naja, wenn man bedenkt, dass man in der ersten Version von System.Configuration in den eigenen Section Handlern XML selbst schreiben und lesen musste... da kann Version 2 auch nicht soviel besser sein.



  • endline. schrieb:

    hustbaer schrieb:

    Und bitte: schreib nicht "Templates" wenn du "Generics" meinst.

    Du musst das Wort Template nicht von C++ & Sonstigem abhaengig machen. Ich weiss die Unterschiede; bei Template denk ich lediglich an das Wort 'Vorlage', was Generics lezten Endes auch sind.

    Ja, natürlich.

    Ich kann auch Uggubuggu statt Tisch sagen, und Blabloink statt Auto. Ist aber etwas hinderlich wenn ich verstanden werden will.

    Was glaubst du wohl warum weder Sun für Java noch MS für C# den Begriff "template" verwendet? Oder warum weder Sun noch MS den Begriff "destructor" für ihre "managed" Sprachen verwendet?



  • hustbaer schrieb:

    endline. schrieb:

    hustbaer schrieb:

    Und bitte: schreib nicht "Templates" wenn du "Generics" meinst.

    Du musst das Wort Template nicht von C++ & Sonstigem abhaengig machen. Ich weiss die Unterschiede; bei Template denk ich lediglich an das Wort 'Vorlage', was Generics lezten Endes auch sind.

    Ja, natürlich.

    Ich kann auch Uggubuggu statt Tisch sagen, und Blabloink statt Auto. Ist aber etwas hinderlich wenn ich verstanden werden will.

    Was glaubst du wohl warum weder Sun für Java noch MS für C# den Begriff "template" verwendet? Oder warum weder Sun noch MS den Begriff "destructor" für ihre "managed" Sprachen verwendet?

    Ich achte das naechste Mal darauf, das richtige Wort zu verwenden 🙂


Anmelden zum Antworten