Ask a questionAsk a question
 

AnswerCasting question

  • Wednesday, November 04, 2009 1:28 PMStevieWright Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi , I have a question on polymorphism: 2 classes

    public class1
    {


    }

    public class2 : class1
    {

    }

    class2 is a carbon copy of class1, except that class 2 is equpped with Linq attributes ([Table], [Column] etc.

    When casting class2 type to class1 type, the type remains that of class2. Is this correct ???  

Answers

  • Thursday, November 05, 2009 11:35 AMDavid M MortonMVP, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Expose B on your service method.  When you generate the WSDL on the client side, it's going to generate only what it knows about B.  You'll notice once the class comes over the wire, it'll no longer be A, it'll be B, but on the server side, it'll remain as A.  That's normal and perfectly acceptable.  

    Think of it this way.  

    HumanBeing stevie = new HumanBeing();
    Mammal someMammal = (Mammal)stevie;

    someMammal doesn't cease to be a HumanBeing.  It was, and always is, a human being.  Only, from someMammal, I can only access the mammal traits and none of the human being specific traits of stevie.  Thus I could say:

    someMammal.BreatheAir();

    But I couldn't say:

    someMammal.SpeakEnglish();

    Though I was able to say:

    stevie.SpeakEnglish();

    Doesn't mean someMammal can't speak english.  It just means that you don't have access to tell someMammal to speak English while referring to it simply as a mammal. 

    If all you need on the client side it the ability to refer to something as a "Mammal", that's fine.  Expose the "HumanBeing" from the service as a Mammal and not as a HumanBeing.  Everything should work just fine. 

    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser

All Replies

  • Wednesday, November 04, 2009 1:32 PMDavid M MortonMVP, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Depends on what you mean by "the type".  There's the instantiated type, and the declared type.  The declared type is the type of the variable, while the instantiated type is the actual type of the value represented by the variable, if that makes sense...

    class1 value = new class2();

    In the above scenario, the declared type is class1, but the instantiated type is class2.  You can still cast the "value" back to class2 without issues, which would give you a variable where the instantiated and declared type is class2. 

    class2 value2 = (class2)value; // declared and instantiated the same

    But to be sure, none of your information is lost when you cast to a base class.
    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser
  • Wednesday, November 04, 2009 11:24 PMStevieWright Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi ,, thx, I understand in full, but it does not answer my question. Maybe some more info:

    I have a class which is part of a client-server app. The class needs to be known on both sides (client and server), because it gets serialised over the wire. The objects, instantiated from the class are stored in an SQL db, meaning that the class declaration also has Table and Column attributes attached to it. The client app is silverlight which does not like Table and Column attributes (there are not the necessary Linq libs in Silverlight).

    To solve this, my idea was to have a server side definition of the class (with the necessary Table/Column attributes, lets call it class A), and a client side definition of the same class, but without the attributes (lets call that class B). I would make B known the the client, and A and B known to the server. A derives from B.

    Now to extract the info from SQL I need to use class A, but I cannot send A over the wire, because the client only knows about class B. I thought that as A derives from B, I could simply cast A to B, and send it over the wire.

    Only when I cast A to B, the type remains A. (????)   
  • Thursday, November 05, 2009 11:35 AMDavid M MortonMVP, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Expose B on your service method.  When you generate the WSDL on the client side, it's going to generate only what it knows about B.  You'll notice once the class comes over the wire, it'll no longer be A, it'll be B, but on the server side, it'll remain as A.  That's normal and perfectly acceptable.  

    Think of it this way.  

    HumanBeing stevie = new HumanBeing();
    Mammal someMammal = (Mammal)stevie;

    someMammal doesn't cease to be a HumanBeing.  It was, and always is, a human being.  Only, from someMammal, I can only access the mammal traits and none of the human being specific traits of stevie.  Thus I could say:

    someMammal.BreatheAir();

    But I couldn't say:

    someMammal.SpeakEnglish();

    Though I was able to say:

    stevie.SpeakEnglish();

    Doesn't mean someMammal can't speak english.  It just means that you don't have access to tell someMammal to speak English while referring to it simply as a mammal. 

    If all you need on the client side it the ability to refer to something as a "Mammal", that's fine.  Expose the "HumanBeing" from the service as a Mammal and not as a HumanBeing.  Everything should work just fine. 

    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser
  • Monday, November 09, 2009 9:45 PMStevieWright Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi .. This is what I have tried, and the class will not go over the wire:

    Class B is exposed to the client

    Class A and B are exposed on server side. A derives from B and is equal in fields/properties etc etc, Except that A (not exposed to the client) is equipped with Linq attributes.

    What will go over the wire:    B objectb = new B();

    What will not go over the wire:  A objecta =new A(); B objectb1 = (B)objecta;
  • Monday, November 09, 2009 10:12 PMStevieWright Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi .. have done a trace and isolated the exception:

    There was an error while trying to serialize parameter http://Spinwizard:CommandResult. The InnerException message was 'Type 'ControlBloks.ArtistInformationBlok' with data contract name 'ArtistInformationBlok:http://Spinwizard' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.  Please see InnerException for more details.

    In this message, "ArtistInformationBlok" is class A. A is not known to the client, and the client is expecting B which is why I am casting from A to B before sending it over the  wire. The message speaks of serialisation problems (not deserialisation), so it seems the service is having problems putting it on the wire.
  • Tuesday, November 10, 2009 8:34 PMStevieWright Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi .. as far as I can see the cause is simple: the contract serializer is not seeing the class as B, although I have explicitly cast it to be of that type. Anybody any idea's ???