Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

UserControl, serijalizacija i refleksija

[es] :: .NET :: UserControl, serijalizacija i refleksija

[ Pregleda: 2915 | Odgovora: 11 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Bope

Član broj: 62233
Poruke: 291
85.222.177.*

Sajt: www.shortsms.me


+4 Profil

icon UserControl, serijalizacija i refleksija03.10.2009. u 19:40 - pre 177 meseci
Ne znam kako da na sto bolji nacin resim ovaj problem:
Napravio sam jednu kontrolu. Vec je sve zavrseno, jedino jos trebam da omogucim cuvanje i ucitavanje svojstava te kontrole. U "property" prozoru korisnik bi trebao da unese adresu adresu fajla u kome su sacuvana svojstva kontrole i onda bi kontrola promenila svoja svojstva u skladu sa onim sto je zapisano u fajlu. Cuvanje svojstava bi slicno funkcionisalo.
Nekako, brute force nacin prvi pada na pamet - pisanje koda za sva svojstva koja trebaju da se sacuvaju ali mislim (bar se nadam) da sve to moze i elegantnije jer kontrola ima stotinak svojstava...
Jel neko rekao serijalizacija? Ne pije vodu...prilikom deserijalizacije ja ne mogu objektu "this" da dodelim deserijalizovani objekat...Opet bi morao da se primeni brute force nacin.

Imao sam ideju da iskoristim refleksiju u kombinaciji sa serijalizacijom tj da refleksijom "izvucem" sva privatna i javna svojstva i da ih serijalizujem i posle prilikom deserijalizacije da iz "this"-a izvlacim jedno po jedno svojstvo i da tim svojstvima dodeljujem vrednosti zapisane u fajlu. Ispostavilo se da ovaj pristup ima dve boljke: pod 1) nisam uspeo da nateram refleksiju da iz objekta "izvuce" privatne promenjljive i 2) uspeo sam da "izvucem" imena javnih promenljivih, ne i njihove vrednosti..

Imao sam ideju da sva svojstva stavim u posebnu klasu koja bi se lako serijalizovala i deserijalizovala. Deserijalizovan objekat "properties" bi onda mogao da zameni postojeci objekat "properties" u kontroli ali i to otpada jer onda korisnik kontrole ne bi mogao da pristupa svojstvima kontrole direktno..

Da li neko ima neki predlog kako bi ovaj problem mogao da se resi? Stvarno vise nisam pametan...Kontrola bi trebala da sacuva svoja svojstva i da prilikom ucitavanja svojstava sama sebe promeni (recimo izgled) u skladu sa onim sto je procitala. Da li mi je sudjeno pisanje koda koji ce da cuva i ucitava jedno po jedno svojstvo?
 
Odgovor na temu

Shadowed
Vojvodina

Član broj: 649
Poruke: 12851



+4784 Profil

icon Re: UserControl, serijalizacija i refleksija03.10.2009. u 19:53 - pre 177 meseci
Ako bas mora instanca da radi popunjavanje podataka sebi, onda mi jedino refleksija pada na pamet. E sad, privatnim promenljivim ne mozes svakako pristupiti, ni serijalizacija ti to ne bi uradila. Ovo pod 2) moze da se uradi, al' ne znam sada napamet a nemam VisualStudio pri ruci.

Druga varijanta ti je da postojeci objekat zamenjujes novim koji dobijas deserijalizacijom. Sad, kako to uraditi zavisi od konkretnog slucaja kako koristis taj objekat.
 
Odgovor na temu

dusty
Predrag Glumac
Zemun, Srbija

Član broj: 15383
Poruke: 549
*.kwcp.net.

Sajt: www.mika.rs


+6 Profil

icon Re: UserControl, serijalizacija i refleksija03.10.2009. u 20:15 - pre 177 meseci
Tja, ako radis u Visual Studio-u, moraces malo da se pomucis, ali cista daktilografija. Otvoris properties te kontrole i ides na propert '(Appliction settings)' pa na '(Property Binding)', odaberes koji property hoces da menjas na toj kontroli (npr. Text ili Checked ....) i u drop downu odaberes 'New' .... ostatak je kucanje, kucanje, kucenje ....
America national sport is called baseballs. It very similar to our sport, shurik, where we take dogs, shoot them in a field and then have a party.
 
Odgovor na temu

Bope

Član broj: 62233
Poruke: 291
85.222.177.*

Sajt: www.shortsms.me


+4 Profil

icon Re: UserControl, serijalizacija i refleksija03.10.2009. u 20:15 - pre 177 meseci
Te promenljive su u "formatu":

private bool _Nesto;
public bool Nesto {
get {
return _Nesto;
}
set {
_Nesto=value;
}
}

Sad mi pada na pamet nesto sto do sad nisam radio - da sve te privatne promenljive stavim u posebnu klasu u kojoj ce sve te privatne promeljive biti javne. Onda bih imao sledece:

internal class Properties {
public bool _Nesto;
}

internal class UserControl {
Properties svojstva=new Properties;
public bool Nesto {
get {
return svojstva._Nesto;
}
set {
svojstva._Nesto=value;
}
}

i da onda serijalizujem (i deserijalizujem) objekat "Properties"... Samo....meni to zvuci malo ne OO...a Vama?

@dusty:
hmmm to do sad nisam radio,morao bih da proverim kako to funkcionise. heh,eto neceg novog :D
 
Odgovor na temu

Igor Gajic

Član broj: 93194
Poruke: 747
77.46.228.*



+987 Profil

icon Re: UserControl, serijalizacija i refleksija03.10.2009. u 20:27 - pre 177 meseci
Code:

using System;
using System.Reflection;

namespace Private
{
    public class TestClass
    {
        private int _vrednost1;
        private string _stringVrednost;
        public int vrednost2;

        public TestClass()
        {
            _vrednost1 = 4;
            _stringVrednost = "testString";
            vrednost2 = 13;
        }
    }

    class Program
    {
        static void Main()
        {
            TestClass obj = new TestClass();

            Type testType = typeof(TestClass);
            foreach (FieldInfo fi in testType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public))
            {
                object reflectionValue = testType.GetField(fi.Name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).GetValue(obj);
                Console.WriteLine(string.Format("{0} : {1}", fi.Name, reflectionValue));
            }

            Console.ReadKey();
        }

    }
}




Ovaj kod ti ispisuje sve promenjive u klasi i private i public. Za postavljanje dovoljno je zameniti GetValue u SetValue


EDIT:

za uzimanje vrednosti property fieldova - bilo private bilo public ima sledeci kod:

Code:


            foreach (PropertyInfo fi in testType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public))
            {
                object reflectionValue =
                    testType.GetProperty(fi.Name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).
                        GetValue(obj, null);
                Console.WriteLine(string.Format("{0} : {1}", fi.Name, reflectionValue));
            }



[Ovu poruku je menjao Igor Gajic dana 03.10.2009. u 21:45 GMT+1]
 
Odgovor na temu

dusty
Predrag Glumac
Zemun, Srbija

Član broj: 15383
Poruke: 549
*.sip.int.bellsouth.net.

Sajt: www.mika.rs


+6 Profil

icon Re: UserControl, serijalizacija i refleksija03.10.2009. u 22:16 - pre 177 meseci
Ignorisi moj post, samo sam letimicno proleteo kroz tvoje pitanje, i zakljucio nesto skroz pogresno. 'Oce to kada zuris da pobegnes sa posla :)

Uglavnom, sada kada sam procitao pitanje, ja bih mislio u pravcu upotrebe XML za cuvanje podataka. Sa kodom koji je Igor dao, znaci preko refleksije, bi pristupao tim podacima za citanje i pisanje, a svaki element u XML bi drzao ime property-a i njegovu vrednost. Tako da ces moci kroz jednu petlju sve da postavis/sacuvas.

BTW Da li su sva svojstva kontrole tipa boolean ?!

America national sport is called baseballs. It very similar to our sport, shurik, where we take dogs, shoot them in a field and then have a party.
 
Odgovor na temu

Bope

Član broj: 62233
Poruke: 291
*.adsl.verat.net.

Sajt: www.shortsms.me


+4 Profil

icon Re: UserControl, serijalizacija i refleksija04.10.2009. u 16:22 - pre 177 meseci
@dusty:
Ne, promenljive su raznih tipova

@Igor Gajic:
Hvala, probacu kod. Nadam se da ce se pokazati kao najbolje resenje :)
 
Odgovor na temu

Bope

Član broj: 62233
Poruke: 291
*.adsl.verat.net.

Sajt: www.shortsms.me


+4 Profil

icon Re: UserControl, serijalizacija i refleksija05.10.2009. u 23:30 - pre 177 meseci
ufffffff....ta serijalizacija me je i u Javi ubijala! Evo o cemu se radi. Resio sam da probam da sva svojstva koja zelim da serijalizujem smestim u ugnezdjenu privatnu klasu i da tu ta svojstva postanu public. Serijalizacijom te privatne klase serijalizujem opis kontrole koju pravim i isto tako deserijalizacijom mogu da ucitam svojstva na osnovu kojih ce kontrola izgraditi svoj izgled.

Code:

public class Glavna {

private class Properties {
public int prvo;
public int drugo;
}

public Glavna() {
Properties Svojstva = new Properties();
Svojstva.prvo=1;
}
}

nadam se da se iz koda vidi ideja - da lako (de)serijalizujem samo odredjena svojstva klase "Glavna". "prvo" i "drugo" ne bi bili vidljivi iz drugih klasa (kao da su deklarisani private u klasi "Glavna"). Vrsim binarnu serijalizaciju na najnormalniji nacin -
Code:
binFormater.Serialize(tok,Svojstva);

i to prodje kako treba, ALI kada pokusam da deserijalizujem ono sto sam sacuvao:
Code:

Svojstva=(Properties)binForm.Deserialize(tok);

javi mi se greska "unable to cast object of type 'Properties' to type 'Properties'.....O cemu se ovde radi? Taman sam pomislio da ce sve da bude kako treba... :(
 
Odgovor na temu

DarkMan
Darko Matesic

Član broj: 20445
Poruke: 572
93.86.81.*

Jabber: DarkMan


Profil

icon Re: UserControl, serijalizacija i refleksija06.10.2009. u 12:27 - pre 177 meseci
Za selektivno cuvanje vrednosti svojstava koristi sistem atributa kao i kod serijalizacije.
U nastavku teksta sam ti dao kod kojim mozes sacuvati vrednosti svojstava nekog objekta u string (metoda SaveProperties) i ucitati vrednosti svojstava nekog objekta iz stringa (metoda RestoreProperties). Ovaj kod ignorise svojstva koja sadrze atribut XmlIgnoreAttribute.
U slucaju da ti imas vise svojstava koja treba ignorisati od onih koja treba sacuvati, prepravi kod da cuva samo svojstva koja sadrze atribut XmlIncludeAttribute.

Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Text;
using System.Xml.Serialization;

namespace WindowsApplication1
{
    public class MemberHelpers
    {
        /// <summary>
        /// Returns TypeConverter for specified type.
        /// </summary>
        public static TypeConverter GetTypeConverter(Type type)
        {
            return (type != null ? TypeDescriptor.GetConverter(type) : null);
        }

        /// <summary>
        /// Returns TypeConverter for specified object.
        /// </summary>
        public static TypeConverter GetTypeConverter(object component)
        {
            return (component != null ? GetTypeConverter(component.GetType()) : null);
        }

        /// <summary>
        /// Sets object field or property to specified string value.
        /// </summary>
        public static bool SetMemberValueAsString(object obj, MemberInfo mi, string value, ref Exception ex)
        {
            if(obj != null && mi != null && (mi.MemberType == MemberTypes.Property || mi.MemberType == MemberTypes.Field)) {
                // use a type converter to convert string value
                try {
                    TypeConverter tc = GetTypeConverter(mi);
                    if(tc != null) {
                        if(mi.MemberType == MemberTypes.Property) {
                            PropertyInfo pi = mi as PropertyInfo;
                            if(pi != null) {
                                if(tc.CanConvertFrom(typeof(string))) {
                                    object val = tc.ConvertFromInvariantString(value);
                                    pi.SetValue(obj, val, null);
                                    return true;
                                } else if(pi.PropertyType == typeof(Type)) {
                                    pi.SetValue(obj, Type.GetType(value), null);
                                    return true;
                                }
                            }
                        } else if(mi.MemberType == MemberTypes.Field) {
                            FieldInfo fi = mi as FieldInfo;
                            if(fi != null) {
                                if(tc.CanConvertFrom(typeof(string))) {
                                    object val = tc.ConvertFromInvariantString(value);
                                    fi.SetValue(obj, val);
                                    return true;
                                } else if(fi.FieldType == typeof(Type)) {
                                    fi.SetValue(obj, Type.GetType(value));
                                    return true;
                                }
                            }
                        }
                    }
                } catch(Exception e) {
                    ex = e;
                }
            }
            return false;
        }
        /// <summary>
        /// Sets object field or property to specified string value.
        /// </summary>
        public static bool SetMemberValueAsString(object obj, MemberInfo mi, string value)
        {
            Exception ex = null;
            return SetMemberValueAsString(obj, mi, value, ref ex);
        }


        /// <summary>
        /// Gets field or property value in string form.
        /// </summary>
        public static bool GetMemberValueAsString(object obj, MemberInfo mi, ref string value, ref Exception ex)
        {
            if(obj != null && mi != null && (mi.MemberType == MemberTypes.Property || mi.MemberType == MemberTypes.Field)) {
                try {
                    TypeConverter tc = GetTypeConverter(mi);
                    if(tc != null) {
                        if(mi.MemberType == MemberTypes.Property) {
                            PropertyInfo pi = mi as PropertyInfo;
                            if(pi != null) {
                                object objValue = pi.GetValue(obj, null);
                                if(tc.CanConvertFrom(typeof(string)) && tc.CanConvertTo(typeof(string))) {
                                    value = tc.ConvertToInvariantString(objValue);
                                    return true;
                                } else if(pi.PropertyType == typeof(Type)) {
                                    value = ((Type)objValue).AssemblyQualifiedName;
                                    return true;
                                }
                            }
                        } else if(mi.MemberType == MemberTypes.Field) {
                            FieldInfo fi = mi as FieldInfo;
                            if(fi != null) {
                                object objValue = fi.GetValue(obj);
                                if(tc.CanConvertFrom(typeof(string)) && tc.CanConvertTo(typeof(string))) {
                                    value = tc.ConvertToInvariantString(objValue);
                                    return true;
                                } else if(fi.FieldType == typeof(Type)) {
                                    value = ((Type)objValue).AssemblyQualifiedName;
                                    return true;
                                }
                            }
                        }
                    }
                } catch(Exception e) {
                    ex = e;
                }
            }
            return false;
        }
        /// <summary>
        /// Gets field or property value in string form.
        /// </summary>
        public static bool GetMemberValueAsString(object obj, MemberInfo mi, ref string value)
        {
            Exception ex = null;
            return GetMemberValueAsString(obj, mi, ref value, ref ex);
        }
        /// <summary>
        /// Gets field or property value in string form.
        /// </summary>
        public static string GetMemberValueAsString(object obj, MemberInfo mi)
        {
            Exception ex = null;
            string value = string.Empty;
            GetMemberValueAsString(obj, mi, ref value, ref ex);
            return value;
        }

        /// <summary>
        /// Replaces special characters in string with specific escape string that can be later restored:
        /// '\\' -> "\\\\"
        /// '\r' -> "\\r"
        /// '\n' -> "\\n"
        /// '\t' -> "\\t"
        /// </summary>
        public static string EscapeSpecialCharacters(string text)
        {
            if(text == null) return null;
            System.Text.StringBuilder result = new System.Text.StringBuilder();
            for(int i = 0; i < text.Length; i++) {
                if(text[i] == '\\') {
                    result.Append("\\\\");
                } else if(text[i] == '\r') {
                    result.Append("\\r");
                } else if(text[i] == '\n') {
                    result.Append("\\n");
                } else if(text[i] == '\t') {
                    result.Append("\\t");
                } else {
                    result.Append(text[i]);
                }
            }
            return result.ToString();
        }

        /// <summary>
        /// Restores special characters in string that where replaced using ReplaceSpecialCharacters method.
        /// Restoration is performed using following patterns:
        /// "\\\\" -> '\\'
        /// "\\r" -> '\r'
        /// "\\n" -> '\n'
        /// "\\t" -> '\t'
        /// </summary>
        public static string RestoreSpecialCharacters(string text)
        {
            if(text == null) return null;
            System.Text.StringBuilder result = new System.Text.StringBuilder();
            for(int i = 0; i < text.Length; i++) {
                if(text[i] == '\\' && i < (text.Length - 1)) {
                    if(text[i + 1] == '\\') {
                        result.Append("\\"); i++;
                    } else if(text[i + 1] == 'r') {
                        result.Append("\r"); i++;
                    } else if(text[i + 1] == 'n') {
                        result.Append("\n"); i++;
                    } else if(text[i + 1] == 't') {
                        result.Append("\t"); i++;
                    } else {
                        result.Append(text[i]);
                    }
                } else {
                    result.Append(text[i]);
                }
            }
            return result.ToString();
        }

        /// <summary>
        /// Saves specified object properties values to a string.
        /// </summary>
        public static string SaveProperties(object obj)
        {
            if(obj != null) {
                StringBuilder s = new StringBuilder();
                foreach(PropertyInfo pi in obj.GetType().GetProperties()) {
                    if(!pi.CanRead) continue;
                    if(pi.GetCustomAttributes(typeof(XmlIgnoreAttribute), true).Length != 0) continue;
                    string value = string.Empty;
                    if(GetMemberValueAsString(obj, pi, ref value)) {
                        if(s.Length > 0) s.Append('|');
                        s.Append(pi.Name + "=" + EscapeSpecialCharacters(value));
                    }
                }
                return s.ToString();
            }
            return string.Empty;
        }

        /// <summary>
        /// Restores specified object properties values from a specified string.
        /// </summary>
        public static void RestoreProperties(object obj, string savedProperties)
        {
            if(obj != null && !string.IsNullOrEmpty(savedProperties)) {
                string[] properties = savedProperties.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                if(properties != null && properties.Length > 0) {
                    Type type = obj.GetType();
                    if(obj is ISupportInitialize) ((ISupportInitialize)obj).BeginInit();
                    foreach(string property in properties) {
                        int index = property.IndexOf('=');
                        if(index > 0) {
                            string name = property.Substring(0, index);
                            if(name.Length > 0) {
                                PropertyInfo pi = type.GetProperty(name);
                                if(pi != null) {
                                    string value = property.Substring(index + 1);
                                    SetMemberValueAsString(obj, pi, RestoreSpecialCharacters(value));
                                }
                            }
                        }
                    }
                    if(obj is ISupportInitialize) ((ISupportInitialize)obj).EndInit();
                }
            }
        }
    }
}
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6042



+4631 Profil

icon Re: UserControl, serijalizacija i refleksija06.10.2009. u 14:46 - pre 177 meseci
Mozda nisam bas najbolje prokapirao sta hoces, ali zar ne moze sve ovo elegantno da se resi kroz ISerializable?

Svi .NET formateri se napravljeni tako da ako [Serializable] klasa implementira ISerializable onda se serijalizacija ne radi proz public propertije i refleksiju vec kroz ISerializable.GetObjectData a deserijalizacija kroz cctor(SerializationInfo information, StreamingContext context). A cim kontrolises sta ide u stream mozes da napravis kakvu god hoces kombinatoriku.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

Bope

Član broj: 62233
Poruke: 291
*.adsl.verat.net.

Sajt: www.shortsms.me


+4 Profil

icon Re: UserControl, serijalizacija i refleksija07.10.2009. u 01:43 - pre 177 meseci
@mmix
mah, desetak linija koda koji bi u tok trebali da naguraju sve sto "uberu" iz klase mi se cinilo jednostavnije nego "rucno" kontrolisanje protoka toka (da se tako izrazim :D). Ja sam napravio gresku sto nisam praznoj,default, UserControl-i napravio neki kontejner koji bi sadrzao sve i koji bi mogao da se glatko upise ili procita (sa sve svojim sadrzajem)...

@DarkMan
Hvala, ovaj kod radi posao! Trebalo mi je malo vremena da ga proucim i primenim. Jel to neki kod sad neta ili nesto domace? :) Ako je sa neta sa kog sajta je?

@svi
Naravno,ako neko ima bolje (jednostavnije) resenje neka javi :)
 
Odgovor na temu

DarkMan
Darko Matesic

Član broj: 20445
Poruke: 572
77.46.221.*

Jabber: DarkMan


Profil

icon Re: UserControl, serijalizacija i refleksija07.10.2009. u 12:44 - pre 177 meseci
Kod je moj ali sam sve te stvari naucio iz primera na internetu.
Evo jednog malog primera http://www.codeproject.com/KB/dotnet/MycroXaml.aspx
 
Odgovor na temu

[es] :: .NET :: UserControl, serijalizacija i refleksija

[ Pregleda: 2915 | Odgovora: 11 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.