Jarda Jirava

Vývojář a architekt řešení postavených na technologii .net framework. Zabývám se jak vývojem webových aplikací za pomoci asp.net, tak také desktopových aplikací winform. Při návrhu řešení a samotném vývoji pak využívám dlouholetých zkušeností se zpracováním obchodní logiky a pravidel aplikací získaných z vývoje komerčních aplikací pro finanční a bankovní instituce.

Microsoft MVP

Microsoft MVP - Client App dev

Silverlight minesweeper

Get Microsoft Silverlight

Navrhi COOL design a vyhraj zkušební let po Evropě!

Poslední příspěvky

22
XII

Marigold o stream.cz je 404

Tak jsem si říkal, že už si teda něco přečtu o tom hojně diskutovaném a probíraném stream.cz, který se včera večer spouštěl. A to přímo, jak se říká, od zdroje, když už se o tom dneska vyrojilo tolik zpráviček. A ono ejhle, místo článku se objevuje chyba 404 s odůvodněním, že se měnil publikační systém. Ach jo, tak místo vánočního počtení, nic. Tak snad někdy příště.

Publikováno pod: krátké postřehy
5
XII

Komponenta roku - sql lokalizace asp.net?

Těší mě, že se mi povedlo udeřit hřebíček na hlavičku. Tedy, alespoň mi to tak připadá a také reakce a příspěvky z okolí, které jsem četl, tomu napovídají.

Komponenta roku

Svoji komponentu, pro lokalizaci asp.net aplikace pomocí databázové tabulky, o které jsem psal již dříve, jsem přihlásil do soutěže komponenta roku. Původní motivace k vytvoření takové komponenty však nepocházela z vyhlášení této soutěže a v té době bylo velice málo informací k tomuto tématu.

Přesto jsem se odhodlal věnovat tomuto tématu a nakonec se mi povedlo uveřejnit svůj příspěvek dříve než vyšel poměrně zajímavý článek na MSDN, který se zabýval rozšířením resource provider modelu v asp.net 2.0 a nastínil i možné řešení s využitím databáze.

Jen několik minut předtím než jsem stihl odeslat svoji přihlášku k účasti v komponentě roku, pak publikoval krátké shrnutí také Scott Guthrie v příspěvku Extending the ASP.NET 2.0 Localization Model with a Database Resource Provider. Nepopisoval v něm jak takový resource provider vytvořit, ale pouze shrnul doposud vyšlé články o tomto tématu. Pokud to myslíte s lokalizací aplikace vážně, potom doporučuji si je přečíst.

A tak se sebe ptám, je to jen náhoda nebo tato oblast trápí více vývojářů v asp.net a dozrál ten správný čas na podobná řešení? Že bych skutečně trefil onen pověstný hřebíček na hlavičku?

O to více je pro mě potěšující fakt, že mé řešení je přeci jen jiné od výše uvedeného a troufám si tvrdit, že více využívá toho, jak je Resource management v .net navržen. Na to jak se tato komponenta bude líbit porotě si však budu muset počkat do poloviny prosince. Vy ji můžete využívat již nyní a několik z vás už tak nejspíše činí. Držte mi palce :-)

Publikováno pod: .net technology
10
XI

Splash screen a ApplicationContext

Vidět reakci ihned po spuštění programu, je přesně to, po čem touží snad každý uživatel aplikace. Vznikají tak různé splash screeny, které informují uživatele co se právě s aplikací děje. Pro tvůrce aplikace je to něco navíc, co dává ke své aplikaci a přitom by se žádná aplikace neměla bez této úvodní obrazovky objevit. Ano, ano, existují výjimky, ale jestliže aplikace je komplexnější a při startu je potřeba provést náročnější inicializaci, je splash screen nejvhodnějším řešením.

Způsobů jak vytvořit tento úvodní formulář určitě existuje několik, já se chci věnovat jednomu z nich, který považuji za velice elegantní a přímočarý. Určitě však nečekejte, že zde objevíte nádherný formulář, mě zajímalo spíše to, co se skrývá tak říkajíc pod kapotou a jak aplikaci vhodně inicializovat.

Použití ApplicationContext třídy

Jednou z možností jak zahájit zpracování smyčky zpráv je vložení instance třídy ApplicationContext jako parametru do metody Application.Run(). Takto vytvořená instance třídy musí obsahovat odkaz na formulář, který bude sloužit jako context. Při zavření tohoto formuláře poté dojde k ukončení aplikace. To ovšem nemusí platit v okamžiku, kdy je přepsána metoda OnMainFormClosed() a vlastnost MainForm je nahrazena za jinou instanci formuláře, který v ten okamžik převezme context aplikace.

Právě tohoto způsobu můžeme využít k vytvoření splash screenu, inicializaci aplikace a zobrazení hlavního okna aplikace.

Inspirace

Teď určitě někteří mohou namítnout, že takových příkladů je možné najít na internetu dostatek. Což je pravda, ale přesto uvedu své řešení, i z toho důvodu, že jsem na stejné nenarazil a většinou všem takovým příkladům scházelo to hlavní, úvodní inicializace aplikace. Můžete tak najít řešení, která používají timer, vykreslují krásné splash screeny a podobně.

Ač by určitě nebyl problém takovou inicializaci doplnit, jsou zde začátečníci, kterým takovýto návod přijde jistě vhod.

Co budeme potřebovat

Určitě to bude nějaký pěkně vyvedený formulář, který bude sloužit jako splash screen. Jakým způsobem bude takový formulář vypadat nechám na vkusu každého, co však bude zajímavější je jeho jedna případně dvě public metody, které budou aktualizovat stav inicializace a informovat uživatele. Dále to bude formulář hlavní, se kterým bude uživatel aplikace pracovat, ten je v plné režii vývojáře. A v neposlední řadě je to třída, ktérou pojmenujeme třeba SplashApplicationContext a jenž je poděděná od třídy ApplicationContext.

SplashApplicationContext

Tato třída provádí vše co budeme potřebovat k zobrazení splasch screenu a následnému zobrazení hlavního okna aplikace. Zároveň se postará o to, že dojde k potřebné inicializaci aplikace (dynamicky nahrávané moduly, připojení ke vzdálenému serveru a natažení úvodních dat, atd.) a to v samostatném vlákně. Po dokončení inicializace, které může trvat proměnlivě dlouhou dobu, pak dojde k zobrazení hlavního formuláře.

Co je důležité si uvědomit je, že inicializace běží v samostatném vlákně aplikace a tak veškerá volání nad prvky formuláře nebo i formulářem samotným musí být kontrolována a vyvolána z vlákna hlavního (UI).

Třída SplashApplicationContext tak může vypadat následovně:

public class SplashApplicationContext : ApplicationContext
{
  private FormSplash _splash;
  private FormMain _main;
  public SplashApplicationContext () {
    _splash = new FormSplash();
    this.MainForm = _splash;
    // Thread.CurrentThread.Name = "mainThreadUI"; abychom snáze identifikovali v jakém vlákně se nacházíme
    Thread thread = new Thread(new ThreadStart(initialize));
    // thread.Name = "initializeThread";
    thread.Start(); // spustíme inicializaci
  }
}

Po provedení konstruktoru se nastartuje inicializace aplikace v samostatném vlákně, ihned poté dochází k vložení instance contextu do smyčky aplikace - Application.Run(new SplashApplicationContext()) - a zobrazení úvodního formuláře.

V metodě initialize() dochází jednak k inicializaci aplikace a také k aktualizaci stavu, který informuje uživatele o prováděných krocích.

private void initialize() {
  _splash.PerformStep("Nahrání uživatelského profilu");
  // zde je nahrání uživatelského profilu
  _splash.PerformStep("Nahrání doplňkových modulů");
  // nahrajeme nutné doplňkové moduly
  splashClose();
}

Po provedení inicializace, na samém jejím konci dochází k volání zavření formuláře. Proč není volána přímo metoda Close() je bystřejším již jasné, nejsme totiž v hlavním vlákně aplikace a tak bychom se mohli dočkat výjimky. Metoda splashClose(), stejně tak jako metoda PerformStep() tak využívají vlastnosti InvokeRequired a případně vyvolají samu sebe.

private void splashClose() {
  if (_splash.InvokeRequired) {
    _splash.Invoke(new MethodInvoker(splashClose));
  } else {
    _splash.Close();
  }
}

Ještě dříve než skončíme a budeme moci naši skvělou aplikaci spustit a kochat se úvodním formulářem, musíme přepsat metodu OnMainFormClosed().

protected override void OnMainFormClosed(object sender, EventArgs e) {
  if (sender is FormSplash) {
    _main = new FormMain();
    this.MainForm = _main;
    this.MainForm.Show();
  } else {
    base.OnMainFormClosed (sender, e);
  }
}

V metodě nejdříve otestujeme, zda dochází k zavření formuláře představujícího náš splash screen, pokud je tomu tak, instancujeme hlavní formulář a přiřadíme ho proměnné MainForm a formulář zobrazíme, tím získá/převezme tento hlavní formulář kontext aplikace. V opačném případě dojde k ukončení aplikace.

Máme hotovo

Tím máme úkol splněn a můžeme aplikaci s dobrým pocitem předat uživatelům, ti pak budou aplikaci vnímat o něco lépe.

Publikováno pod: .net technology , builder.cz , code snippet
8
XI

.NET 3.0 je venku, a co dál

Byl to jistě náročný den pro vývojáře Microsoftu, a ještě náročnější den pro spousty blogerů být prvními, kdo uvede, že .net 3.0 je venku a můžeme jej začít používat. Jenže je tu otázka, a co dál? Jsem spíše praktický člověk a tak moje první poohlédnutí bylo po nástrojích, které s sebou tato verze .net přinese, pro vývojáře.

Nástroje pro vývojáře

Téměř každý příspěvek vypadal totožně, čtyři odkazy a stručné, téměř oficiální, sdělění. Michal přidal ještě obrázek, což nastínilo, o jak malou změnu s posunem v major čísle se jedná.

Když jsem však procházel co vše je možné si stáhnout navíc pro vývojáře, byl jsem nemile zaskočen. Téměř žádná podpora pro tyto nové věci zde není. Je vydána jen jedna extenze pro WWF, a možnost stažení si CTP (pouze CTP?) vezre pro WPF a WCF. Docela mi také schází Expression Designery. A to jsem se ještě nepustil do studia SDK, které je určeno jen pro serverové systémy.

Marketingové postesknutí

Nemohu se pokládat za marketingového specialistu a už vůbec nemohu rozhodovat o tom, jak bude Microsoft vydávat své produkty. Určitě se dokážu smířit s tím, že tato verze nese označení .net 3.0, méně však s tím, že schází větší podpora pro vývojáře při vydání takového produktu. Byl bych určitě raději, kdybych zároveň s vydáním běhového prostředí dostal plnou podporu pro vývoj. Oželel bych jistě měsíc nebo i dva, než se takto radovat a přitom být v kotku duše smutný.

Publikováno pod: .net technology , krátké postřehy
29
X

Lokalizujeme asp.net aplikaci

Jistě každý zná situaci, kdy je nutné lokalizovat aplikaci a nabídnout ji uživatelům v několika jazykových mutacích. .NET framework toto řeší velice elegantně pomocí resource souborů a ResourceManagera. V asp.net 2.0 je celé řešení velice důmyslně řešeno, kdy je možnost jít ještě dále a nabízí se tak mít lokální a globální resource soubory, o tom, jak to celé funguje napsal poměrně zajímavý blogspot také Robert Haken v článku Lokalizace snadno a rychle - explicitní lokalizace. Jak už to však bývá, ne vše je tak kulaté jak se zdá.

Je to už nějaká chvíle co byl na konferenci o .net na fóru builder.cz položen dotaz ohledně možnosti lokalizace asp.net aplikací. Tenkrát jsem slíbil, že se pokusím sepsat nějaký krátký příspěvek na toto téma a zpřístupnit tak své nabyté zkušenosti také ostatním.

O co se konkrétně jedná? Autora dotazu zajímalo, zda je možné použít k lokalizaci texty, které má umístěny v databázi. Odkazů na řešení daného úkolu se našlo hnedka několik, ale většinou se jednalo o takové řešení, které nebylo elegantní (alespoň mě se nezdálo). Převážně se taková řešení opírala o skutečnost, že je nutné explicitně provést lokalizaci daného textu z codebehind stránky tj. vytvořit si nějaký vlastní DbResourceManager a pomocí metod GetString provádět lokalizaci jednotlivých textů. Přitom je velice elegantní a dostupné řešení v asp.net 2.0, a to použítí meta značek a nebo alespoň použití explicitní lokalizace tedy uvedení této konstrukce.

property="<%$ Resources: LokalizovanyText %>"

Jaká je tedy možnost lokalizace v případě, že nechci používat resource soubory? Mám já, jako vývojář, nějakou možnost si říci, že všechny texty budou uloženy třeba v databázi a odsud se budou načítat? A to ještě pokud možno s co nejmenším úsilým, které k lokalizaci bude nutné udělat? Nebude nutné se uchýlit k nějakému vlastnímu formátu řešení lokalizace, byť by bylo sebelépe navrženo, a upustit tak od modelu, který je v současné chvíli podporován v asp.net 2.0? Nesetkám se zde s podobným problémem, který nastavá u celkové konfigurace aplikace, kdy je možné používat ConfigurationManager pouze ve spojitosti s .config souborem a přitom je občas vhodné mít konfiguraci uloženu i jinde

Na poslední otázky je však v souvislosti s lokalizací možné odpovědět, nikoliv. Tím řešením je napsat si vlastní ResourceProviderFactory a implementovat několik rozhraní případně dědit z tříd již existujících. To celé potom spojit v jeden funkční celek pomocí konfiguračního souboru web.config v jeho sekci globalization a to atributem resourceProviderFactoryType.

O tom, jak si napsat takový jednoduchý ResourceProvider, kterým je možné lokalizovat asp.net aplikace a vesměs pouze přepínat pomocí konfigurace mezi jednotlivými možnostmi, se rozepíšu příště.

27
X

Odhalujeme .net - Deserializace - řešení

Aneb, jak se také nedočkat správné odpovědi. Zřejmě jsem zvolil velice záludnou otázku a přestože si ji přečetlo jistě více jak 70 lidí, žádný se nepokusil o její zodpovězení.

Nebudu tedy více napínat všechny ty, kteří čekají na správné řešení. Problémem, na který jsem narazil, bylo zpracovávání tzv. bílých znaků, whitespacehandling. Jak už jsem se zmínil, bylo potřeba serializovat a zpětně deserializovat malé konfigurační objekty a mezi jednotlivými vlastnostmi se objevila i samotná mezera.

Ta se ovšem při použití vstupního parametru typu StringReader nepřevedla zpět. Tudíž bylo nutné explicitně vytvořit XmlTextReader a teprve ten použít pro deserializaci xml řetězce. Pokud se podíváte blíže na implementaci metody Deserialize() např. pomocí Reflectoru, zjistíte, že se interně vytváří právě XmlTextReader a nastavuje se mu property WhitespaceHandling. A právě v nastavení této property ležel ten hlavní důvod a úskalí celého řešení.

Takže cena pro tuto chvíli zůstává pro mě.

Publikováno pod: .net technology , code snippet