\


 Friday, 09 May 2008
LINQ II - přetypovávání i vnořených anonymních datových typů z jiné assembly

V předchozím spotu jsem byl schopen pracovat s anonymními datovými typy, i když byly dotazy a výsledné sady dat vytvořeny v jiné assembly. Odstranění vrozené xenofobie v praxi.:)

Náš kód ale vygeneruje výjimku, jestliže anonymní datový typ z jiné assembly obsahuje další vnořené anonymní datové typy jako v následujícím upraveném příkladu. Vlastnost InnerAT vrací další anonymní datový typ, který  pro zajímavost obsahuje odkaz ještě na další anonymní datový typ.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LINQTEST
{
    public class TestAT
    {
        public static object GetResult()
        {
            string[] rows = { "Toyota", "Lexus", "Audi" };

            var test = from row in rows
                       select new
                       {
                           FirstLetter = row[0],
                           Index = 110,
                           Original = row,
                           InnerAT = new { X = row[1], B = new {A=1}}
                       };
            
            return test;

        }
    }
}

Řešení spočívá v úpravě extenzí a to tak, že přidáme privátní metodu GetTypeInstance a přeneseme do ní většinu kódu z extenze ToAnonymousType. Metoda GetTypeInstance při neshodě datového typu očekávaného parametrem "našeho - v naší assembly dostupného" konstruktoru anonymního datového typu a datového typu vlastnosti anonymního datového typu z "cizí" assembly rekurzivně přenese data z "cizího" anonymního datového typu do "našeho".

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Reflection;
using System.Collections;
using LINQTEST;

namespace LINQAnonymous
{
    /// <summary>
    /// Rozšíření pro LINQ
    /// </summary>
    static class RSLinqExtensions
    {

        /// <summary>
        /// Metoda přetypuje objekt na anonymní typ, jehož struktura byla předána v parametru <paramref name="prototype"/>
        /// </summary>
        /// <typeparam name="T">Kompilátorem odvozený anonymní typ</typeparam>
        /// <param name="prototype">Prototyp se strukturou anonymního typu</param>
        /// <returns>Instanci anonymního typu, nebo null, jestliže konverzi nelze provést</returns>
        /// <remarks>Metoda se pokusí převést data z různých assembly</remarks>
        public static T ToAnonymousType<T>(this object obj, T prototype)
                                        where T: class
        {
            
            
            T atiObj = obj as T;
            
            if (atiObj == null)
            {
                
                atiObj = GetTypeInstance(obj, prototype.GetType()) as T;
               
            }
                                                     
            return (atiObj);
        }
    

        private static object GetTypeInstance(object obj, Type expected)
        {
            object atiObj = null;

            ConstructorInfo constructorInfo = expected.GetConstructors()[0];
                
                if (constructorInfo == null)
                {
                    return null;
                }

                ParameterInfo[] paramInfos = constructorInfo.GetParameters();                
                PropertyInfo[] origProperties = obj.GetType().GetProperties();
                

                if (paramInfos.Count() != origProperties.Count())
                {
                    return null;
                }

                object[] paramArgs = new object[paramInfos.Count()];


                for (int i = 0; i < paramArgs.Length; i++)
                {
                    PropertyInfo origProperty = origProperties.Where(prop => prop.Name == paramInfos[i].Name).FirstOrDefault();

                    if (origProperty == null)
                    {
                        return null;
                    }

                    object val = origProperty.GetValue(obj, null);
                    if (origProperty.PropertyType != paramInfos[i].ParameterType)
                    {
                        val = GetTypeInstance(val, paramInfos[i].ParameterType);
                    }

                    paramArgs[i] = val;
                }

                atiObj = constructorInfo.Invoke(paramArgs);
                return atiObj;
        }
        /// <summary>
        /// Metoda vrátí
        /// </summary>
        /// <typeparam name="T">Kompilátorem odvozený anonymní typ</typeparam>
        /// <param name="prototype">Prototyp se strukturou anonymního typu</param>
        /// <returns>List instancí anonymního typu, nebo null, jestliže konverzi nelze provést</returns>
        /// <remarks>Metoda se pokusí převést data z různých assembly</remarks>
        public static List<T> CastToList<T>(this object obj, T prototype)
                                 where T : class
        {
            List<T> list = new List<T>();
            IEnumerable<T> enumerable = obj as IEnumerable<T>;

            if (enumerable != null)
            {
                list.AddRange(enumerable);
            }
            else
            {
                    IEnumerable enumObjects = obj as IEnumerable;
                    if (enumObjects == null)
                    {
                        return null;
                    }
                    
                foreach (object enumObject in enumObjects)
                    {
                        T currObject = ToAnonymousType(enumObject, prototype);
                        if (currObject == null)
                        {
                            //K čistění listu by neměl být důvod, ale garantujeme, že nevrátíme částečně naplněný list
                            list.Clear();
                            return list;
                        }

                        list.Add(currObject);
                    }
                
            }

            return list;
        }
    }
    

Při přetypovávání stačí stále jen zadat prototyp anonymního datové typu.

 

//Anonymní typ z jiné assembly!
            var result2 = TestAT.GetResult().CastToList(new {FirstLetter = default(char), 
                                                        Index =default(int),
                                                        Original = default(string),
                                                        InnerAT = new { X = default(char), B = new { A = default(int) } }
            })
                                                       ;
            foreach (var res in result2)
            {
                Console.WriteLine(res.FirstLetter);
                Console.WriteLine(res.Original);
            }


            Console.WriteLine(TestAT.
                                    GetResult().
                                    CastToList(new
                                    {
                                        FirstLetter = default(char),
                                        Index = default(int),
                                        Original = default(string),
                                        InnerAT = new { X = default(char), B = new { A =default(int)} }
                                    }
                                    ).
                                    Where(car => car.FirstLetter == 'T')
                                     .FirstOrDefault()
                                     .ToString());
            Console.ReadLine();


Friday, 09 May 2008 09:09:26 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  .NET Framework | ASP.NET | Compact .Net Framework | LINQ | Windows Forms


 Thursday, 08 May 2008
LINQ - anonymní typ deklarovaný v jedné assembly dostupný v metodách další assembly?
.Net Framework

Anonymní datové typy v LINQu nelze použít jako návratový typ z metody a jediný způsob, jak anonymní typ z metody předat, je použít jako návratovou hodnotu typ object, protože v .Net Frameworku - jak je všeobecně známo - všechny třídy přímo či nepřímo dědí z třídy Object. Navíc platí, že anonymní typ je kompilátorem vždy deklarován jako internal a jeho použití je tak striktně omezeno na jednu assembly.

Jde o rozumné omezení a anonymní datové typy bychom neměli zneužívat k nesmyslům typu "hezká syntaxe pro generování objektů Dictionary", které si našly cestu i do připravovaného (a už dnes "přehypovaného") MVC frameworku pro ASP.NET.

V různých diskuzích se ale stále dokola objevuje dotaz, jak anonymní typ z metody vráti. A každé omezení se dá samozřejmě obejít - když nefunguje ani bodový systém na silnicích, proč nenajít hrubý trik ve stylu "osoby blízké" i pro erozi různých omezení u anonymního datového typu. :) Znovu alibisticky varuji všechny před zařazením následujících nehezkých triků do svého arzenálu běžných postupů při vývoji, protože všechny postupy spoléhají na chování kompilátoru C#, které není garantováno a které se může v další verzi nebo i jen při vydání service packu .Net Frameworku bez varování změnit.

Pro vrácení anonymního datového typu z metody použijeme hezký hack od Tomáše, který se ujal pod názvem "Cast By Example". Zjednodušeně řečeno - sice nemůžeme používat při přetypovávání názvy anonymních datových typů (tříd), protože anonymní datové typy jsou generovány až při kompilaci, ale můžeme kompilátoru dát při přetypování "vzor", jaký anonymní datový typ nám bude vyhovovat. Podrobnosti si můžete najít v odkazovaném článku Tomáše Petříčka  = zde jen připomenu, že technika využívá současného chování kompilátoru, který pro různé deklarace anonymních datových typů se stejnými vlastnostmi generuje v jedné assembly vždy právě jednu třídu.

Napsal jsem jednoduše použitelné extenze, které vám dovolí nejen přetypovat jednu instanci "object" na anonymní datový typ, ale můžete přetypovat množiny záznamů na (anonymně ;-)) typovou kolekci List<NějakýAnonymniTyp>, a dokonce je možné jednoduše použít anonymní datové typy z jiné assembly.

 

/// <summary>
    /// Rozšíření pro LINQ
    /// </summary>
    static class RSLinqExtensions
    {

        /// <summary>
        /// Metoda přetypuje objekt na anonymní typ, jehož struktura byla předána v parametru <paramref name="prototype"/>
        /// </summary>
        /// <typeparam name="T">Kompilátorem odvozený anonymní typ</typeparam>
        /// <param name="prototype">Prototyp se strukturou anonymního typu</param>
        /// <returns>Instanci anonymního typu, nebo null, jestliže konverzi nelze provést</returns>
        /// <remarks>Metoda se pokusí převést data z různých assembly</remarks>
        public static T ToAnonymousType<T>(this object obj, T prototype)
                                        where T: class
        {
            
            
            T atiObj = obj as T;
            
            if (atiObj == null)
            {

                ConstructorInfo constructorInfo = typeof(T).GetConstructors()[0];
                
                if (constructorInfo == null)
                {
                    return null;
                }

                ParameterInfo[] paramInfos = constructorInfo.GetParameters();                
                PropertyInfo[] origProperties = obj.GetType().GetProperties();
                

                if (paramInfos.Count() != origProperties.Count())
                {
                    return null;
                }

                object[] paramArgs = new object[paramInfos.Count()];


                for (int i = 0; i < paramArgs.Length; i++)
                {
                    PropertyInfo origProperty = origProperties.Where(prop => prop.Name == paramInfos[i].Name).FirstOrDefault();
                    
                    if (origProperty == null)
                    {
                        return null;
                    }
                                        
                    
                    paramArgs[i] = origProperty.GetValue(obj, null);                    
                }
                
                atiObj = constructorInfo.Invoke(paramArgs) as T;
            }
            
            return (atiObj);
        }
    
        /// <summary>
        /// Metoda vrátí
        /// </summary>
        /// <typeparam name="T">Kompilátorem odvozený anonymní typ</typeparam>
        /// <param name="prototype">Prototyp se strukturou anonymního typu</param>
        /// <returns>List instancí anonymního typu, nebo null, jestliže konverzi nelze provést</returns>
        /// <remarks>Metoda se pokusí převést data z různých assembly</remarks>
        public static List<T> CastToList<T>(this object obj, T prototype)
                                 where T : class
        {
            List<T> list = new List<T>();
            IEnumerable<T> enumerable = obj as IEnumerable<T>;

            if (enumerable != null)
            {
                list.AddRange(enumerable);
            }
            else
            {
                    IEnumerable enumObjects = obj as IEnumerable;
                    if (enumObjects == null)
                    {
                        return null;
                    }
                    
                foreach (object enumObject in enumObjects)
                    {
                        T currObject = ToAnonymousType(enumObject, prototype);
                        if (currObject == null)
                        {
                            //K čistění listu by neměl být důvod, ale garantujeme, že nevrátíme částečně naplněný list
                            list.Clear();
                            return list;
                        }

                        list.Add(currObject);
                    }
                
            }

            return list;
        }
    }

Komentáře u metod by měly dostatečně popisovat funkci extenzí. Metoda ToAnonymousType předpokládá, že chcete přetypovat na instanci anonymního typu (např. při použití metody Single v LINQu), metoda CastToList pracuje s množinou (IEnumerable<T>) instancí anonymního datového typu. Většina kódu v obou metodách ošetřuje situaci, kdy pracujete s anonymním datovým typem z jiné (referencované) assembly, jehož data je potřeba přenést do instance anonymního datového typu v aktuální assembly.

Použití extenzí - nejprve u anonymního datového typu deklarovaného v assembly, ve které je také náš LINQ dotaz.

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Reflection;
using System.Collections;
using LINQTEST;

class Program
    {

        //Anonymní typ deklarovaný v této (exe) assembly
        private static object GetLetters()
        {
           string[] names = {"Rene", "Petra", "Kamilka"};

           var test = from name in names
                      select new {FirstLetter = name[0], Index=1};
           return test;
        }


        static void Main(string[] args)
        {
            var result = GetLetters().CastToList(new {FirstLetter = default(char),
                                                      Index =default(int)}
                                                 );
            foreach (var res in result)
            {
                Console.WriteLine(res.FirstLetter);
            }

}

Metodě CastToList jsme predali "vzor" anonymího datového typu (new {FirstLetter = default(char), Index =default(int)}) a hodnoty vlastností jsme u prototypu inicializovali s využitím klíčového slova default. V metodě Main v cyklu foreach je funkční intellisense a můžeme pracovat zcela typově s proměnnou res. Jenom zdůrazním, že nyní žádná reflexe nebyla použita! Metoda CastToList s využitím automatické typové inference kompilátoru pouze zkopírovala prvky v IEnumerable<T> do našeho typového generického Listu.

if (enumerable != null)
            {
                list.AddRange(enumerable);
            }

Reflexe je využita při konverzi anonymního typu deklarovaného v jiné assembly. Předpokládejme, že v jiné assembly nazvané např. LINQTest máme další metodu vracející množinu dat skrytou opět za obecným rozhraním "služebníka zcela neužitečného" neboli třídy object.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LINQTEST
{
    public class TestAT
    {
        public static object GetResult()
        {
            string[] rows = { "Toyota", "Lexus", "Audi" };

            var test = from row in rows
                       select new { FirstLetter = row[0],
                                    Index=110,
                                    Original = row
                                  };
            
            return test;

        }
    }
}

Zkompilovanou assembly LINQTest zareferencujeme v našem projektu. Kód pro práci s anonymní datovým typem v jiné assembly se z pohledu uživatele LINQ extenze nijak nezměnil od předchozího příkladu.

 

class Program
    {


        static void Main(string[] args)
        {
            //Anonymní typ z jiné assembly!
            var result2 = TestAT.GetResult().CastToList(new {FirstLetter =  default(char), 
                                                        Index =default(int),
                                                        Original = default(string)}
                                                       );
            foreach (var res in result2)
            {
                Console.WriteLine(res.FirstLetter);
                Console.WriteLine(res.Original);
            }


            Console.WriteLine(TestAT.
                                    GetResult().
                                    CastToList(new
                                    {
                                        FirstLetter = default(char),
                                        Index = default(int),
                                        Original = default(string)
                                    }).
                                    Where(car => car.FirstLetter == 'T')
                                     .FirstOrDefault()
                                     .ToString());
            Console.ReadLine();
        }
    }

Jak si můžete všimnout, po cyklu foreach si požádám o data z jiné assembly znovu a poté nad vrácenou typovou kolekci vytvořím další projekci. A ani mě nemusí zajímat, že se mi pod rukama zcela změnil typ používaných objektů. :-)

Docela zábavná záležitost ne? ;-)

LINQ II - přetypovávání i vnořených anonymních datových typů z jiné assembly



Thursday, 08 May 2008 15:00:43 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  .NET Framework | ASP.NET | Compact .Net Framework | LINQ | Windows Forms


 Wednesday, 07 May 2008
Stále neopravený bug při volání metody HttpWebRequest.BeginGetResponse?

Ještě při psaní jedné aplikace běžící na .Net Framework verze 2.0 jsem objevil podivnou chybu, kdy se při asynchronním stahování stránek pomocí třídy HttpWebRquest asynchronní přístup skoro nelišil od synchronní verze. Metoda BeginGetResponse vrátila řízení volajícímu kódu teprve poté, co došlo ke stažení celé stránky. Dle Microsoftu se problém objevoval i ve verzi 1.1 a příčinou jsou  "antipatie" mezi metodou BeginGetResponse a konfigurací DNS.

 

Myslel jsem si, že tento bug je ve verzi 3.5 odstraněn, ale dnes jsem zjistil, že bugy stejně jako kočky mají minimálně devět životů. U mě stačí -někdy-zadat adresu začínající na "www" a z asynchronního volání je volání synchronní. Zvláštní a k vzteku je, že že nelze stoprocentně napsat návod na reprodukci bugu (zkoušel jsem vyčistit i DNS cache). Bug se ale projevuje při připojení přes ADSL, O2 HSDPA i TMO GPRS/EDGE.

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace WebTest
{
    class Program
    {
        static void Main(string[] args)
        {
            bool done = false;
            WebRequest req = WebRequest.Create("http://www.vyvojar.cz");
            req.BeginGetResponse(delegate(IAsyncResult result)
                                      {

                                          done = true; 
                                          Console.WriteLine(String.Format("Done: {0}", DateTime.Now.ToLongTimeString()));
                                          req.EndGetResponse(result).Close();                                          
                                          Console.WriteLine();
                                          
                                      }

                                  ,null);

            while(!done)
            {
                Console.WriteLine("Not done");
            }

            Console.WriteLine("Stop");
            Console.ReadLine();
        }

        
    }
}

Jedinou obranou proti náhodným výkyvům v matrixu registrovaných služeb z předzjednaného řádu a Microsoftem sponzorované harmonie (Disclaimer: Tato obrana zabírá jen na popsaný bug, ale proti výkyvům univerza pocházejících od zeleného viru, a to i v jeho totálně dezorientované a nejméně hostilní mutaci "Džamila Stehlíková", je zcela bemocná ;-)) je po mnoha mých pokusech nahrazení názvu domény v url adrese její IP adresou (jestliže máte pod kontrolou nastavení webového serveru, na kterém běží stránky-webové služby, protože jinak nemusí samozřejmě ip adresa v hlavičce HOST dostačovat...). Ip adresu zjistíme jednoduše voláním metod z třídy DNS. Volání metod třídy DNS kupodivu žádné zpoždění nevykazuje...

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Threading;

namespace WebTest
{
    class Program
    {
        static void Main(string[] args)
        {
            bool done = false;
            
            IPHostEntry address = Dns.GetHostEntry("www.vyvojar.cz");
            HttpWebRequest req = WebRequest.Create(String.Format("http://{0}", address.AddressList[0].ToString())) as HttpWebRequest;             
            req.BeginGetResponse(delegate(IAsyncResult result)
                                      {
                                          
                                          done = true; 
                                          Console.WriteLine(String.Format("Done: {0}", DateTime.Now.ToLongTimeString()));
                                          req.EndGetResponse(result).Close();                                          
                                          Console.WriteLine();
                                          
                                      }

                                  ,null);

            while(!done)
            {
                Console.WriteLine("Not done");
            }

            Console.WriteLine("Stop");
            Console.ReadLine();
        }

        
    }
}


Wednesday, 07 May 2008 12:48:42 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  .NET Framework | Web Services


 Monday, 05 May 2008
Pozvánka na přednášku Pasti, strasti a propasti nativního/řízeného (managed) vývoje pro zařízení s operačním systémem Windows Mobile

Pozvánka na přednášku  Pasti, strasti a propasti nativního/řízeného (managed) vývoje pro zařízení s operačním systémem Windows Mobile

Ve čtvrtek 15.5.2008 přednáším na WUG v Hradci Králové o vývoji aplikací pro Windows Mobile. Jestliže vás téma zajímá a máte cestu okolo, rád vás uvidím. ;)

Místo konání: Střední škola aplikované kybernetiky, Hradecká 1151, Hradec Králové (www.ssakhk.cz)
Datum a čas akce: 15.5.2008 17:00:00
Stránka WUG s podrobnostmi o akci: http://www.wug.cz/Aktuality/tabid/36/ctl/Detail/mid/492/ItemId/124/language/cs-CZ/Default.aspx

 



Monday, 05 May 2008 17:00:08 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Compact .Net Framework | Mobilitky | Net Monitor | Wifi Profiles Windows Mobile


GSM Net Monitor a WiFi profily mají vlastní stránky

Freewarové aplikace GSM Net Monitor a WiFi profily mají (už přibližně měsíc) své vlastní stránky, aby informace o nich nezůstaly utopeny pouze ve spotech na blogu a já jsem se zbavil dotazů na ICQ (nebo v to alespoň naivně doufám, než celé ICQ pošlu na hnojiště dějin=> na hnojišti končí produkty, které si nezaslouží místo na ordinérním smetišti dějin a mezi ně paskvil zvaný ICQ v posledních  letech beze všech pochybností patří) , kde se dá stáhnout poslední verze nebo kde je možné o aplikacích diskutovat.

WiFi profily

GSM Net Monitor

BTW: Ani úpěnlivé prosby o přidání nějaké takové nebo onaké funkcionality do programů nezrychlí vývoj aplikací, protože aplikace jsou hračky vyvinuté jen jako vedlejší efekt komerční aplikace (GSM Net Monitor), anebo mi přišlo jednodušší napsat WiFi profily, než stále dokola ručně Petře (manželce) nastavovat PDA.

Pro mé účely jsou aplikace plně funkční a práce na nich pokračuje jen ve volném čase. Žádné prosby ani hrozby vývoj neurychlí. Vývoj bude rychlejší, když použijete magické Paypal tlačítko Donate na této stránce, případně na moji adresu přímo zašlete láhev ostřejšího pití (Johnie Walker, Four Roses, Tulamore Dew), nebo nějaké výborné víno (Pálava - výběr z hroznů, Tokajske víno, Archivní Modrý Portugal, Chardonnay, Rulandské modré, Rulandské šedé ...). :-D



Monday, 05 May 2008 16:19:48 (Central Europe Standard Time, UTC+01:00)       
Comments [2]  Mobilitky | Net Monitor | Wifi Profiles Windows Mobile


 Thursday, 24 April 2008
Vlastní reakce na podrženi stylu uživatelem (zobrazení kontextového menu)

Další z triků pro Compact .Net Framework, na který se lidé často ptají. Chcete sami zareagovat na podržení stylu místo výchozího zobrazení kontextového menu, což zajišťuje výchozí obsluha události přímo v CNF? Přes P/Invoke je to možné.

private const uint GN_CONTEXTMENU = 1000; 
private const uint SHRG_RETURNCMD = 0x00000001; 


[StructLayout(LayoutKind.Sequential)] 
public class SHINFO 
{ 
       public uint cbSize = 0; 
       public IntPtr hwndClient = IntPtr.Zero; 
       public int x = 0; 
       public int y = 0; 
       public uint dwFlags = 0; 
} 
[DllImport("aygshell", SetLastError = true)] 
private static extern uint SHRecognizeGesture(SHINFO shrg); 


//Obsluha udalosti MouseDown formulare/ovladaciho prvku
private void mouseDown(object sender, MouseEventArgs e) 
{ 

   SHINFO shinfo = new SHINFO(); 
   shinfo.cbSize = (uint)(Marshal.SizeOf(shinfo)); 
   shinfo.hwndClient = this.Handle; //handle formulare/ovladaciho prvku
   shinfo.x = e.X; 
   shinfo.y = e.Y; 
   shinfo.dwFlags = SHRG_RETURNCMD; 
   if (SHRecognizeGesture(shinfo) == GN_CONTEXTMENU) 
   {
     //nase reakce 
  } 
}

V nativním kódu můžeme vlastním zpracováním gesta GN_CONTEXTMENU odstranit nepříjemnou a snad od počátku přítomnou chybu v MFC, která způsobí, že se animace ("tečky opisující kruh") zobrazí 2x. Ukázka z Today pluginu (čisté API, ne MFC).

 

 

SHRGINFO shrg;
HMENU hMenu;

shrg.cbSize = sizeof(shrg);
shrg.hwndClient = m_hWnd;
shrg.ptDown.x = point.x;
shrg.ptDown.y = point.y;
shrg.dwFlags = SHRG_RETURNCMD ;

POINT screenPoint = point;
ClientToScreen(m_hWnd, &screenPoint);


if (!tabControl.HasFocus())
{
:PostMessage(GetParent(), TODAYM_TOOKSELECTION, (WPARAM)m_hWnd, 0);

}

if (SHRecognizeGesture(&shrg) == GN_CONTEXTMENU) 
{
//Nas kod
}


Thursday, 24 April 2008 12:11:30 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Compact .Net Framework | Mobilitky


 Friday, 18 April 2008
Existuje konverze na typ int? A jsme schopni detekovat existenci konverze za běhu aplikace?

Na builderu padl dotaz, jak za běhu aplikace zjistit, zda lze nějaký typ konvertovat na int a přitom zohlednit i uživatelské konverze. Sice nevím, k čemu by se dala informace využít:), když už si  kompilátor "jen to své" u konverzí řekl - užitečnost informace je srovnatelná s užitečnosti permanentky do harému obdržené post mortem. (Kvazi)problém se dá částečně vyřešit s využitím podivných hacků. Přesto dávám kód sem s vírou, že někdo vymyslí něco lepšího, nebo mi alespoň sdělí, k čemu by se taková informace dala využít. A per analogiam se tak vyřeší i trýznivá aporie (ne)obdržené permanentky. :)

static class TypeExtensions
    {
         public static bool HasToIntConversion(Type type)
         {
        
                 Type intType = typeof(int);
                 Type currentType = type;
                    
                 Type[] floatTypes = {typeof(float), typeof(double), typeof(decimal)};
                 if (currentType.IsPrimitive||
                     currentType.IsEnum ||
                     Array.IndexOf(floatTypes, currentType) >= 0)
                   
                {
                    return true;
                }

                
                else
                {

                    foreach (MethodInfo info in currentType.GetMethods())
                    {
                        Console.WriteLine(info.Name);
                        if (info.Name.Contains("op_Implicit") || info.Name.Contains("op_Explicit"))
                        {
                            if (info.ReturnType.Equals(intType))
                            {
                                return true;
                            }
                        }
                        
                    }

                }

                return false;
            }
        
             
        public static bool HasToIntConversion(this object obj)
        {
            return HasToIntConversion(obj.GetType());           

        }
    
        public static bool HasToIntConversion<T>()
        {
            return HasToIntConversion(typeof(T));
        }
            
    }

Použití je jednoduché:

 

class ConvertibleToInt
    {
        private int x=5;
        
        
        public ConvertibleToInt()
        {

        }
    
        public static implicit operator int(ConvertibleToInt instance)
        {
            if (instance == null)
            {
                throw new InvalidCastException();
            }
            
            return instance.x;
        }

    }


    class ExplicitConvertibleToInt
    {
        private int x = 5;


        public ExplicitConvertibleToInt()
        {

        }

        public static explicit operator int(ExplicitConvertibleToInt instance)
        {
            if (instance == null)
            {
                throw new InvalidCastException();
            }

            return instance.x;
        }

    }

class Program
    {
        static void Main(string[] args)
        {

            ConvertibleToInt conv = new ConvertibleToInt();
            Console.WriteLine(conv.HasToIntConversion());
            
            
            Console.WriteLine(TypeExtensions.HasToIntConversion<short>());
            Console.WriteLine(TypeExtensions.HasToIntConversion<decimal>());
            Console.WriteLine(TypeExtensions.HasToIntConversion(5));


            Console.WriteLine(TypeExtensions.HasToIntConversion<ConvertibleToInt>());
            Console.WriteLine(TypeExtensions.HasToIntConversion<ExplicitConvertibleToInt>());
            
            Console.ReadLine();
            
        }
}


Friday, 18 April 2008 16:56:38 (Central Europe Standard Time, UTC+01:00)       
Comments [5]  


 Tuesday, 01 April 2008
Google Android a proč se na Androidu podílí i tak soudná firma, jakou je společnost HTC?

Protože se mě v posledních dvou měsících pár lidí na diskuzních fórech ptalo na to, co říkám platformě Android od Googlu a posléze na to, proč si myslím, že Androida podporuje HTC, dávám své poznámky sem, abych je nemusel posílat každému zvlášť. Uznávám, že první část byla by se dala shrnout  jednou holou větou: "Nemám rád Google". :) Aby ale spot nepůsobil tak jednostranně - pořád bych raději Androida než tu tretku od Applu zvanou iPhone, která se mi nejprve líbila, ale poté, co jsem ji měl jeden den na hraní  a prošel jsem všechny zdůrazňované přednosti iPhonu (hele, jak mi rotuje displej a jak mohu zvětšit část stránky v prohlížeči atd.),  a znovu jsem se podíval na cenovku, jen jsem se dlouho smál. Ověřil jsem si, že stále žiju v báječném světě, kde vás samotná rozjuchaná reklama vyzve, abyste kašlali na image, což Apple fanoušci zvládají dokonale a iPhone samozřejmě kupují většinou jen proto, že se jim samotným líbí a ne že by si chtěli honit triko před podobně nezávislými kámoši. A mimochodem  - Apple dle posledních "analýz" prý nemá skoro žádné náklady na marketing - v postorwellovském světě slovo nic znamená (ale fakt jen přibližně :) ) 1/3 zisku za rok 2006.


" Domníváte se, že se prosadí mobilní linuxová platforma Google Android, která je open source => méně závislá na oficiální implementaci výrobce?"

Ne, podle mě se neprosadí a bude to pořádný průšvih - ale takový experiment si Google dovolit může a neúspěch (prozatím) nijak neohrozí jeho hlavní "business".  Kdyby za Androidem nestál Google, (skoro) nikdo se o tuto platformu nebude zajímat - jenže dnes vše, co dělá Google, má ihned kolem sebe mediální aureolu něčeho úžasného a důležitého. Google je obr na hliněných nohou - Google se sice rozkročil do mnoha oblastí, ale kromě vyhledávání mu z žádné oblasti, o kterou se zajímá, netečou žádné zajímavé peníze - a já osobně žadný další vydatný zdroj peněz ani v budoucnu nevidím. A do těch hliněných nohou ho na každém nepřátelském území, které se snaží svým "přátelským" přístupem anektovat, s gustem a požitkářskou vervou nakopne jakákoli firma, která nechce přijít o svůj současný tržní podíl. A že by Google sesadil z trůnu Nokii nebo Microsoft? Dobrý vtip... Vždyť jeho "peněženka" nedokáže ani pořádně konkurovat PayPalu.

Heslo "don´t be evil" je nádherně líbivé, na věčně naivní dušičky stále ještě svojí setrvačností působí a každá firma je stejně jako politická strana vděčná za zapálené "užitečné idioty". A Google se zatím jako každá normální firma snaží už jen maximalizovat zisk pro své akcionáře. 
Lehké koketování Google s Open Source je různými obskurními blogy a webziny odměňováno vtíravou, neplacenou a skoro bez výhrad kladnou reklamou po celém internetu.  Komunitní tamtamy stále duní, aktivity Googlu propagují zdarma nadšení jedinci v různých diskuzních fórech a pro Google zapálené blogy, jež šíří jakoukoli novou zprávu či jen fámu z Googlu jako největší událost od zvěstování evangelia. Nezáleží na tom, jestli Google mluví o Androidu, aktualizuje Page Rank, kupuje vývojářům nové hračky nebo se Larry či Sergej na dnešek špatně vyspali, protože si zapomněli rozsvítit svoji novou lávovou lampičku, ale vše, co dělá Google, je přece důležité, skvělé a současné firmy jako Nokia a Microsoft patří na zaneřáděné smetiště dějin, protože nechápou, jak nový svět vnímá moderní a vždy in komunitní a pro věci zdarma zapálená dušička, která v Googlu našla znovu ten věčně hledaný ideál kapitalisty s duší altruisty a líbivostí milostných charitek Aglai, Eufrosyne a Thalei.  A to nemluvím o tom, že Google milují a jsou mu zcela oddáni  - a to nejen proto, že je živí -  noví a pelem moderní techniky ovátí mágové, čarodějové, zaklínači a alchymisté, ti rozkošní a právoplatní dědici magistra Kellyho, jimiž jsou různí SEO a SEM specialisti, kteří z křišťálové koule věští, co ten jejich miláček Google asi pozměnil ve svých hodnotících algoritmech a jak z klientů vydyndají další peníze na posun ze stého místa ve vyhledávání na úžasné padesáté deváté. 

Google Android bude mít těžký život - jsem zvědavý, zda se vůbec podaří donosit Andoida až k úspěšnému porodu, zda mu nepřátelské sudičky(= jiné firmy) hned v kolébce místo věštby raději rovnou pro jistotu nezakroutí krkem, nebo zda neskončí po čase v izolaci, kam slušní výrobci ani dodavatelé aplikací nechodí a bude rád, když po několikaletém marném úsilí získat významný podíl na trhu a vytvořit kolem sebe stabilní vývojářskou komunitu, bude alespoň paběrkovat a jako žebrák sbírat drobty ze stolu, na kterém už dnes holdují obžerství jiní - a právem, protože jsou mnohem schopnější než anemický a do všech stran rozkročený Google.

Některé zajímavé příspěvky k Androidu:
http://unqualified-reservations.blogspot.com/2007/11/five-problems-with-google-android.html
http://arstechnica.com/news.ars/post/20071219-google-android-plagued-by-dysfunctional-development-process.html

Kdybych rozhodoval o strategii HTC, byl bych pro uvedení Gogle Androidu také.  Proč?

1) HTC se snaží poslední rok etablovat jako samostatná značka srovnatelná s Nokií či SE a nevnímaná jen jako mlčenlivý výrobce zajímavých přístrojů prodávaných pod značkou mobilních operátorů.  Když se v tiskové zprávě Htc zmiňuje v jedné řadě s Nokií a dalšími, je to samozřejmě pěkný a hlasitý signál veřejnosti, jak má společnost HTC nyní vnímat.

2) Jak jsem psal výše, všechny zprávy, co se i jen letmo týkají Googlu, mají dnes zajištěnu úžasnou publicitu ve spřízněných médiích a po letech spekulací na téma "Google a mobilní telefon" je oznámení vlastní ambiciózní mobilní platformy tučné sousto pro média, po kterém lačně chňapnou a v mnoha variantách předkousané a většinou nadšené přijaté předhodí i svým čtenářům. Důležité iformace o HTC se s minimálními náklady objeví v klíčových médiích.

3) V HTC dokonale využili příležitosti a hrozbu exkluzivní spolupráce s Googlem, kterého dnes Microsoft určitě vnímá jako největšího konkurenta, mohou pasovat do role beranidla, aby si u Microsoftu vymohli lepší podmínky spolupráce.

4) Od počátku mají v HTC přístup k interním údajům o Androidu, o jeho (ne) úspěšnosti, a podle toho mohou snadno měnit svoji strategii na trhu s přístroji Windows Mobile. A jsem zvědav, zda pro oba světy bude HTC dodávat HW shodné přístroje, anebo neodolá pokušení (tajné a lukrativní dohodě? :-) a pro Android dodá zařízení hardwarově horší a méně zajímavá než pro Windows Mobile.

5) Kdyby měl náhodou Android úspěch, HTC je od počátku tím, kdo se podílí na slávě a úspěchu Androidu a hlavně má další příjmy pro své akcionáře. Když Android neuspěje, HTC to nijak nehrozí  - jejich klíčový business je ve zcela jiné oblasti.

6) Spekulace - dovedu si představit, že dle interních analýz HTC je navzdory současnému úspěchu nejméně perspektivním OS Symbian. Kdyby válka na trhu mobilních operačních systemů donutila Nokii přejít na Windows Mobile (viz současné spekulace), nebo migrovat k Androidu, mohlo by HTC z tápání Nokie při přechodu na novou platformu vytřískat větší podíl na trhu mobilních zařízení, protože s oběma OS by měli v HTC více zkušeností.



Tuesday, 01 April 2008 11:33:07 (Central Europe Standard Time, UTC+01:00)       
Comments [5]  Mobilitky


 Thursday, 10 January 2008
Wifi profily verze 0.0.4

Verze 0.0.4.

Stáhnout cab: !!!Důležité: Není povoleno cab soubor dále redistribuovat nebo vystavovat na svých stránkách - musí být stažen z  mých stránek!!!

Diskuze k programu:

1) Sjednocení EN a CZ verze - podpora pro libovolné množství dalších jazyků.
Aplikace se spustí v angličtině, do češtiny se přepnete vybráním položky Language menu a zvolením CZ v dalším dialogu.

2) Možnost nastavení internetové http proxy. Podpora vrácení se k poslednímu stavu připojení před aplikací proxy.  Abyste požívali proxy v Pocket IE a dalších programech, musíte nastavit u wifi sítě, že se připojuje k profilu work.  Nové nastavení vás připojí přes proxy na internet   - nechci zabíhat do detailů, "global wide proxy" jsou poměrně komplikovaná záležitost a pro jejich programové nastavení neexistuje pořádná dokumentace. :(
Pokud bude zájem, mohu přidat socks proxy.

3) Možnost samostatně z menu nebo i u každého profilu nastavit, zda se má wifi odpojit při vypnutí zařízení. Upozorňuji, že u některých zařízení musíte pro uplatnění hodnot (podobně jako je tomu při zapínání wifi) sami zapnout wifi po soft resetu z manažera připojení před nastavením způsobu odpojování wifi.

4) Možnost spustit po aplikaci profilu (resp. po připojení k wifi síti - platné SSID) libovolný program. Jestliže není wifi síť připojena nebo nelze detekovat připojení k wifi síti, je program spuštěn po uplynuti 20 s.

Pro program je možné zadat příkazový řádek. V příští verzi nebudete muset zadávat cestu k programu sami do textového pole, ale v dialogu si program sami vyberete.

5) Možnost vytvořit si zástupce přímo pro profil (např. v Total Commanderu CE) -  profil lze aplikovat vytvořením zástupce s příkazem v následujícím tvaru.
"<Cesta k exe>" <Nazev profilu>

Tedy např. tento zástupce aktivuje profil s názvem MujProfil.
"\Storage Card\Program Files\RStein\WifiProfiles\RStein.WifiProfiles3.exe"  MujProfil


6) Možnost nainstalovat aplikaci na SD kartu.

7) Volba v profilu, zda má být po aktivaci profilu zapnuta wifi.

8) Po zvolení DHCP=Ano jsou nepoužívané volby v konfiguraci profilu skryty.

Za nesprávné používání aplikace ani za možné vzniklé škody a následné hard resety nenesu žádnou odpovědnost! To pro jistotu připomínám . :)

Enjoy :)


 

 



Thursday, 10 January 2008 20:40:54 (Central Europe Standard Time, UTC+01:00)       
Comments [1]  Mobilitky | Nativní kód | Wifi Profiles Windows Mobile


 Thursday, 03 January 2008
Synchronizace TV programu

Program pro stahovani TV programu pro aplikaci TVProgram od cloveka s nickem milaczeque.

Synchronizer pro TV:
Vlastnosti:
1) Desktopova aplikace (nebezi na PDA) napsana v .Net frameworku.
2) Automaticka synchronizace pri pripojeni zarizeni k ActiveSyncu.
4) Programy. ktere se stahuji, muzete upravit v souboru DownloadConfig.txt. Stejne tak muzete stahovat porady bez popisku (staci v url nastavit klic informace na 0). Vzdy ale musite mit v URL klic {DAYS_PLACEHOLDER}, kam synchronizer doplnuje informace, pro jake dny chcete stahnout program. V souboru RStein.SimpleWMDownloader.exe.muzete pomoci klice NumberOfDays nastavit, na kolik dni dopredu chcete stahovat program config (add key="NumberOfDays" value="3"/ ) - nastaveny 3 dny.
5) Zkusebni verze - za nic nerucim, neexistuje instalacni program.

Pozadavky:
Na pocitaci musi byt nainstalovan .Net Framework 2.0 (lze stahnout z adresy http://www.microsoft.com/downloads/details.aspx?familyid=0856eacb-4362-4b0d-8edd-aab15c5e04f5&displaylang=en)
Na pocitaci musi byt nainstalovan ActiveSync.

1) Stahnete si synchronizer z adresy  http://blog.renestein.net/__DOWNLOAD/TVSynchronizer.zip
2) Rozbalte soubory do adresare na svem pocitaci (napr. do Program Files)
3)  Otevrete v notepadu soubor DownloadConfig.txt a upravte cestu k souboru s programem na PDA (puvodne \storage card\Program Files\TVProgram\tvprogram.txt). Cesta k souboru s TV programem je na konci souboru PO STREDNIKU - vse, co je pred strednikem ani strednik samotny, NIJAK NEMENTE. Soubor ulozte.
4) Spustte soubor RStein.SimpleWMDownloader.exe s parametrem -r.     RStein.SimpleWMDownloader.exe -r   
Aplikace prida podklic pod klic v registrech HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\AutoStartOnConnect - muzete sami zkontrolovat pres regedit.

Pripojte PDA: Pokud jste vse dobre nastavili, do PDA se vam stahne aktualni TV program.

Id programu na palm.sitina.

1 ČT1
2 ČT2
3 Nova
4 Prima
5 HBO
6 HBO2
7 ČS Film
8 Film+
9 Cinemax
10 Hallmark
11 Praha
12 Galaxie Sport
13 EuroSport
14 EuroSport2
15 ČT24
16 24cz
17 Jetix
18 Minimax
19 Anime+
20 Spektrum
21 Discovery
22 AnimalPlanet
23 National Geographic
24 Reality TV&
25 AXN
26 Romantica
27 Óčko
28 TV Paprika
29 Markíza
30 JOJ
31 STV1
32 STV2
33 TA3
34 TVP1
35 TVP2
36 Polonia
37 TVN
38 TVN7
39 Polsat
40 TV4
41 RTL
42 RTL2
43 SuperRTL
44 PRO7
45 SAT1
46 3SAT
47 ORF1
48 ORF2
49 ARD
50 DSF
51 VOX
52 ZDF
53 VIVA
54 VIVA+
55 MTV
56 MTV2
57 MTV Base
58 MTV Hits
59 VH1
60 VH1 Classic
61 Cartoon Network
62 Boomerang
63 TCM
64 Club
65 BBC Prime
66 ESPN Classic Sport
67 Extreme
68 Private Blue
69 Private Gold
70 CNN
71 Mezzo
72 Viasat Explorer
73 Viasat History
74 Filmbox
75 Zone Reality
76 RTL klub
77 TV2
78 Nonstop Kino
79 ČT4 Sport
80 Nova Cinema
81 Zone Reality




Thursday, 03 January 2008 12:47:56 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Mobilitky