[ giger @ 18.08.2008. 23:10 ] @
Evo ovako pravim neki servis cije bi sve metode vracale ovu klasu

Code:

[XmlRoot(ElementName = "OperationStatus")]
    public class OperationStatus
    {
        private string _statusCode;
        private string _statusMessage;
        private object _object;

        [XmlElement]
        public string StatusCode
        {
            get
            {
                return _statusCode;
            }
            set
            {
                _statusCode = value;
            }
        }

        [XmlElement]
        public string StatusMessage
        {
            get
            {
                return _statusMessage;
            }
            set
            {
                _statusMessage = value;
            }
        }

        [XmlElement(ElementName = "Result")]
        public object Object
        {
            get
            {
                return _object;
            }
            set
            {
                _object = value;
            }
        }
    }


Zamislio sam da u ovaj "Object" (Result) stavljam svoje objekte . To mogu biti prosti tipovi, ili klase ili pak kompleksne klase.

Medjutim naisao sam na problem, ako KLASA_A sadrzi ArrayList objekata klase KLASA_B, tada dobijam ovu gresku:

Citat:

System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidCastException: Unable to cast object of type 'KLASA_A' to type 'KLASA_B'.
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write1_Object(String n, String ns, Object o, Boolean isNullable, Boolean needType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write5_OperationStatus(String n, String ns, OperationStatus o, Boolean isNullable, Boolean needType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write10_OperationStatus(Object o)
at Microsoft.Xml.Serialization.GeneratedAssembly.OperationStatusSerializer4.Serialize(Object objectToSerialize, XmlSerializationWriter writer)
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
at System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o)
at System.Web.Services.Protocols.XmlReturnWriter.Write(HttpResponse response, Stream outputStream, Object returnValue)
at System.Web.Services.Protocols.HttpServerProtocol.WriteReturns(Object[] returnValues, Stream outputStream)
at System.Web.Services.Protocols.WebServiceHandler.WriteReturns(Object[] returnValues)
at System.Web.Services.Protocols.WebServiceHandler.Invoke()



Jel ima neko ideju, jel radio neko nesto slicno?

Hvala unapred,
pozdrav
[ mmix @ 19.08.2008. 12:39 ] @
Za pocetak, dva saveta:

- nemoj imenovati identifikatore rezervisanim recima i imenima drugih tipova tako sto ces promeniti case. C# jeste case sensitive, ali CLR nije, prizivas sebi probleme. Umesto Object, stavi InnerObject ili nesto slicno.
- ako koristis C#3.0 ne treba ti poseban storage za propertije koji imaju set i get koji samo citaju i pisu iz tog storage-a. Umesto

Code:

        private string _statusCode;

        [XmlElement]
        public string StatusCode
        {
            get
            {
                return _statusCode;
            }
            set
            {
                _statusCode = value;
            }
        }


dovoljno je da napises

Code:

        [XmlElement]
        public string StatusCode { get; set; }


a kompajler ce sam rezervisati private storage i napraviti get i set accessore.


Sto se tice greske, dobijas je pri serijalizaciji Object propertija. Nije mi bas najjasnije zasto serijalizer pokusava da castuje A u B, ajd okaci relevantne delove KLASA_A i KLASA_B. ONo sto je sigurno je da je serijalizacija kaskadna, sto ce reci sve instance koje se nalaze u drvu objekta moraju biti serializable.

[ giger @ 19.08.2008. 14:06 ] @
Pozdrav i hvala ti

U pravu si za imenovanje, promenio sam u InnerObject, a sto se tice ovog ostalog, nisam znao za tu sintaksu, ali i radim na .NET 2.0 tako da ....

Da se sad vratim na problem serijalizacije...

Ovako sam definisao klase:
Code:

public class KLASA_A
    {
    private ArrayList _klasaBList

       [XmlArray( KLASA_B_List), XmlArrayItem("KLASA_B", typeof(KLASA_B))]
        public ArrayList KLASA_B_List
        {
            get
            {
                return _klasaBList
            }
            set
            {
                _klasaBList = value;
            }
        }
     }


public class KLASA_B
    {
    private int id;

    [XmlElement]
        public int ID
        {
            get
            {
                return id;
            }
            set
            {
                id;= value;
            }
        }
    }   


E, sad problem je kad hocu u InnerObject da vratim samo ArrayList od objekata KLASA_A, tad imam probleme, a kad koristim sledecu klasu ciji objekat postavim u InnerObject, tad sve radi:

Code:

[XmlRoot("KLASA_A_LIST_Result")]
    public class KLASA_A_LIST
    {
        private ArrayList _klasaAList

        public KLASA_A_LIST()
        {
            _klasaAList= new ArrayList();
        }

        [XmlArray("KLASA_A_LIST"), XmlArrayItem("KLASA_A", typeof(KLASA_A))]
        public ArrayList [XmlArray("KLASA_A_LIST"),
        {
            get
            {
                return _klasaAList
            }
            set
            {
                _klasaAList= value;
            }
        }
    }


..., ali dobijem visak xml tagova u rezultatu

nesto ovako

Code:

<Result xsi:type="KLASA_A_LIST">
    <KLASA_A_LIST> <-- Ovaj mi je tag visak i on me nervira
        <...ovde je lista objekata tipa KLASA_A, sa ugnjezdenim kolekcijama KLASA_B>
    <KLASA_A_LIST>
</Result>




Samo da napomenem da na onoj OperationStatus klasi imam i ovaj atribut, koji je potreban da bi ovo ovako radilo:

Code:

[XmlInclude(typeof(KLASA_A_LIST))]


A, mozda ne razumem problematiku dovoljno, mozda i ne moze drugacije, nego ovako kako sam izveo...???
[ mmix @ 19.08.2008. 17:56 ] @
Pa, mislim da ne moze drugacije pod ovim okolnostima. ArrayList je untyped niz, pa kad serijalizujes u XML serijalizer ne zna sta je u njemu. Iz tog razloga koristis XmlArray i XmlArrayItem atribute za B listu unutar A objekta (cime si u WSDLu kreirao complex type ArrayOfKLASA_B), medjutim kad imas instancu A liste nemas nigde deklarisano kakav je to Xml niz i iz cega se sastoji niti postoji nacin da to definises preko XmlInclude, samim tim serijalizacija puca (doduse greska je malo van mozga, a uzrok je to sto web servis pokusava da "spase stvar" i taj niz pretoci u onaj za koji ima WSDL contract, a to je ArrayOfKLASA_B, pokusvajuci da castuje).

Sto ne razlmislis o upotrebi tipiziranih nizova ili Collection<T> genericsa (ako ti treba dinamicka kontrol niza) i onda dodas

Code:

        [XmlInclude(typeof(KLASA_A[]))]                    // za  tipizirani niz

// ili

        [XmlInclude(typeof(Collection<KLASA_A>))]     // za generics


pred web metod ili pred OperationStatus klasu i dobices ono sto trazis, u WSDLu ce biti kreiran ArrayOfKLASA_A i niz/kolekcija ce biti serijalizovan bez uokvirujuceg taga.
[ giger @ 19.08.2008. 19:22 ] @
Svaka cast, koji si car... Evo uspelo je. Hvala i na pojasnjenjima...


PS. Znam da si mi nesto dosta pomagao i pre oko godinu i po dana...

Puno hvala