none
WeakDelegate + další o delegátech a eventech

    Dotaz

  • Zajímalo by mne, zda bude v nějaké budoucí verzi frameworku (nejlépe 2.0 SPx, abych to mohl použít i ve Windows98) něco jako WeakDelegate se stejnou funkčností, jen s odkazem na objekt v podobě WeakReference. Uznávám, že vyvstane otázka, jak se chovat při "zavolání" takového delegáta, který už nemá odkaz (neboť mu ho GC sebral). Dle používané filosofie by asi došlo k výjimce.

     

    Dále by mne zajímalo, jak jsou dnes třídy používané pro delegáty navrženy. Zajímá mne totiž ne zcela tradiční příklad a to dlouhý seznam posluchačů (tedy registrovaných objektů+metoda). Podle toho, co jsem viděl v ROTORu (implementace fx2.0 pro FreeBSD, kterou vydal přímo Microsoft jako SCCLI - Shared Source CLI) tak je použito stejné metody jako v ArrayList a tudéž se nehodí pro dlouhé seznamy, které se budou v čase měnit.

     

    Obě otázky směřují ke stejnému cíli a to centralizované nastavení (jazyka, fontů, barev, ...), které bude moci uživatel za běhu měnit. Přiznám se, že jsem ještě nenastudoval principy lokalizace v .NET, ale obávám se, že je to stejné jako s Javou a tedy na přepínání jazyků za běhu je to nepoužitelné (...když vám volá slovensky mluvící bulhar z maďarska a potřebuje něco vysvětlit, tak se vám přepnutí jazyka náramně hodí, zvlášť, když už jste jeho problém vyřešili a teď mu máte vysvětlit, kam má kliknout).

     

    Odpověď po pravdě moc nečekám, svůj problém vyřeším: implementace nečeho na způsob

    WeakEventManager (.NET 3.0), spíše však jako v Javě - "WeakList" (WeakHashMap nepotřebuji, své uzle obousměrného spojového seznamu s WeakReference na sebe si mohou pamatovat a odebírat je v Dispose(bool)) a implementují předepsaný interface na způsob "SettingsChangedListener".

    úterý 8. ledna 2008 18:29

Odpovědi

  • Zdravim,

     

     firda napsal:

    Zajímalo by mne, zda bude v nějaké budoucí verzi frameworku (nejlépe 2.0 SPx, abych to mohl použít i ve Windows98) něco jako WeakDelegate se stejnou funkčností, jen s odkazem na objekt v podobě WeakReference. Uznávám, že vyvstane otázka, jak se chovat při "zavolání" takového delegáta, který už nemá odkaz (neboť mu ho GC sebral). Dle používané filosofie by asi došlo k výjimce.

     

    WeakCokoliv jste přeci schopen implementovat právě pomocí WeakReference, protože WeakReference zapouzdřuje typ object, do kterého dáte cokoliv, tedy i delegáta. A pokud Vám vadí chybějící strong-typing, tak si můžete udělat vlastní generickou obálku Weak<T>, s kterou se Vám bude lépe pracovat.

     

    Jaký contract byste od WeakDelegate požadoval, co nejde splnit pomocí WeakReference?

     

     firda napsal:

    Dále by mne zajímalo, jak jsou dnes třídy používané pro delegáty navrženy. Zajímá mne totiž ne zcela tradiční příklad a to dlouhý seznam posluchačů (tedy registrovaných objektů+metoda). Podle toho, co jsem viděl v ROTORu (implementace fx2.0 pro FreeBSD, kterou vydal přímo Microsoft jako SCCLI - Shared Source CLI) tak je použito stejné metody jako v ArrayList a tudéž se nehodí pro dlouhé seznamy, které se budou v čase měnit.

     

    Pokud máte pocit, že pro Váš konkrétní scénář je .NET implementace delegátů nevyhovující, pak Vám nic nebrání napsat si vlastní implementaci návrhového vzoru Observer. Je to na pár řádek kódu a můžete si tam udělat optimalizace pro Váš scénář:
    http://en.wikipedia.org/wiki/Observer_pattern

     

     firda napsal:

    Obě otázky směřují ke stejnému cíli a to centralizované nastavení (jazyka, fontů, barev, ...), které bude moci uživatel za běhu měnit. Přiznám se, že jsem ještě nenastudoval principy lokalizace v .NET, ale obávám se, že je to stejné jako s Javou a tedy na přepínání jazyků za běhu je to nepoužitelné (...když vám volá slovensky mluvící bulhar z maďarska a potřebuje něco vysvětlit, tak se vám přepnutí jazyka náramně hodí, zvlášť, když už jste jeho problém vyřešili a teď mu máte vysvětlit, kam má kliknout).

     

    Lokalizace v .NET se zpravidla odehrává na úrovni resources a jejich volba se řídí přepnutím příslušného Threadu do příslušné Culture, pro ASP.NET viz např.

    http://knowledge-base.havit.cz/asp-net/Lokalizace-webovych-aplikaci-explicitni-resources.aspx

    pro WinForms je to obdobné. Delegáty tam nikde nepotřebujete.

    Stejnětak pro ostatní centralizované nastavení si myslím, že není běžný scénář motat do toho delegáty.

    středa 9. ledna 2008 8:43
    Moderátor

  •  Robert Haken napsal:

    Lokalizace v .NET se zpravidla odehrává na úrovni resources a jejich volba se řídí přepnutím příslušného Threadu do příslušné Culture, pro ASP.NET viz např.

    http://knowledge-base.havit.cz/asp-net/Lokalizace-webovych-aplikaci-explicitni-resources.aspx

    pro WinForms je to obdobné. Delegáty tam nikde nepotřebujete.

    Stejnětak pro ostatní centralizované nastavení si myslím, že není běžný scénář motat do toho delegáty.



    Ano, to je všechno moc hezké, ale jde mi o přepnutí za běhu. Předpokládám, že v aplikaci pro Windows (nikoliv ASP) se v InitComponents prostě vygeneruje něco jako bTlacitko.Text = GetResourceString("KlickProTextTohoTlacitka"). Když změním jazyk, tak se ale nezmění text již vytvořených komponent, je v podstatě třeba zavřít úplně všechno, uložit a více méně spustit každé okno znovu, nebo ne?

    A nebo si to hold napsat, centralizovat a u každé komponenty si pamatovat onen klíč, držet spoják a v protected metodě SettingsChanged(...) dělat totéž co v InitComponents ohledně lokalizace.



    Přepnutí za běhu - stačí si uvědomit, že při odbavování každého requestu se vykonává životní cyklus celé stránky znovu, tedy včetně nastavení vlastností Text z resources. Stačí tedy na začátku životního cyklu requestu (stránky) přepnout currentThread.UICulture a je to. Viz ten můj článek, opravdu je to tam popsané.

    Robert Haken, Microsoft MVP ASP/ASP.NET, HAVIT, s.r.o., www.havit.cz, http://knowledge-base.havit.cz
    středa 18. února 2009 21:00
    Moderátor

Všechny reakce

  • Zdravim,

     

     firda napsal:

    Zajímalo by mne, zda bude v nějaké budoucí verzi frameworku (nejlépe 2.0 SPx, abych to mohl použít i ve Windows98) něco jako WeakDelegate se stejnou funkčností, jen s odkazem na objekt v podobě WeakReference. Uznávám, že vyvstane otázka, jak se chovat při "zavolání" takového delegáta, který už nemá odkaz (neboť mu ho GC sebral). Dle používané filosofie by asi došlo k výjimce.

     

    WeakCokoliv jste přeci schopen implementovat právě pomocí WeakReference, protože WeakReference zapouzdřuje typ object, do kterého dáte cokoliv, tedy i delegáta. A pokud Vám vadí chybějící strong-typing, tak si můžete udělat vlastní generickou obálku Weak<T>, s kterou se Vám bude lépe pracovat.

     

    Jaký contract byste od WeakDelegate požadoval, co nejde splnit pomocí WeakReference?

     

     firda napsal:

    Dále by mne zajímalo, jak jsou dnes třídy používané pro delegáty navrženy. Zajímá mne totiž ne zcela tradiční příklad a to dlouhý seznam posluchačů (tedy registrovaných objektů+metoda). Podle toho, co jsem viděl v ROTORu (implementace fx2.0 pro FreeBSD, kterou vydal přímo Microsoft jako SCCLI - Shared Source CLI) tak je použito stejné metody jako v ArrayList a tudéž se nehodí pro dlouhé seznamy, které se budou v čase měnit.

     

    Pokud máte pocit, že pro Váš konkrétní scénář je .NET implementace delegátů nevyhovující, pak Vám nic nebrání napsat si vlastní implementaci návrhového vzoru Observer. Je to na pár řádek kódu a můžete si tam udělat optimalizace pro Váš scénář:
    http://en.wikipedia.org/wiki/Observer_pattern

     

     firda napsal:

    Obě otázky směřují ke stejnému cíli a to centralizované nastavení (jazyka, fontů, barev, ...), které bude moci uživatel za běhu měnit. Přiznám se, že jsem ještě nenastudoval principy lokalizace v .NET, ale obávám se, že je to stejné jako s Javou a tedy na přepínání jazyků za běhu je to nepoužitelné (...když vám volá slovensky mluvící bulhar z maďarska a potřebuje něco vysvětlit, tak se vám přepnutí jazyka náramně hodí, zvlášť, když už jste jeho problém vyřešili a teď mu máte vysvětlit, kam má kliknout).

     

    Lokalizace v .NET se zpravidla odehrává na úrovni resources a jejich volba se řídí přepnutím příslušného Threadu do příslušné Culture, pro ASP.NET viz např.

    http://knowledge-base.havit.cz/asp-net/Lokalizace-webovych-aplikaci-explicitni-resources.aspx

    pro WinForms je to obdobné. Delegáty tam nikde nepotřebujete.

    Stejnětak pro ostatní centralizované nastavení si myslím, že není běžný scénář motat do toho delegáty.

    středa 9. ledna 2008 8:43
    Moderátor
  • Též zdravím.

     Robert Haken napsal:

    WeakCokoliv jste přeci schopen implementovat právě pomocí WeakReference, protože WeakReference zapouzdřuje typ object, do kterého dáte cokoliv, tedy i delegáta.


    To není tak úplně pravda. Když budu držet delegáta přes WeakReference, tak zmizí. Mohu si z toho delegáta vzít Target a Method a udělat:


    Code Block

    class WeakDelegate {
      private WeakReference target;
      private MethodInfo method;
      public WeakDelegate(Delegate copy) {
        target = new WeakReference(copy.Target);
        method = copy.Method;
      }

      public object Invoke(params object[] args) {

        object o = target.Target;

        if (!target.IsAlive) return null;

        return method.Invoke(o, args);

      }

    }

     

     Robert Haken napsal:

    Jaký contract byste od WeakDelegate požadoval, co nejde splnit pomocí WeakReference?


    Myslím že zmíněné řešení nastiňuje v čem je problém, nemohu držet delegáta přes WeakReference, potřebuji přes WeakReference držet objekt, na kterém je třeba vykonat metodu. Když tento objekt (Target, nikoliv delegát) nebude k dosažení, tak není WeakDelegate dále třeba.


    Řešení, které jsem uvedl, je pro mnohé případy dostačující, ale je nesystémové a dle dokumentace se může stát, že mi jednou Delegate při pokusu o získání MethodInfo vyhodí vyjímku, pokud půjde o privátní metodu, což je běžná praxe.


     Robert Haken napsal:

    Pokud máte pocit, že pro Váš konkrétní scénář je .NET implementace delegátů nevyhovující, pak Vám nic nebrání napsat si vlastní implementaci návrhového vzoru Observer. Je to na pár řádek kódu a můžete si tam udělat optimalizace pro Váš scénář:

    http://en.wikipedia.org/wiki/Observer_pattern



    Diť, už v původním příspěvku jsem si sám odpověděl a to řešením právě na tento způsob.

     Robert Haken napsal:

    Lokalizace v .NET se zpravidla odehrává na úrovni resources a jejich volba se řídí přepnutím příslušného Threadu do příslušné Culture, pro ASP.NET viz např.

    http://knowledge-base.havit.cz/asp-net/Lokalizace-webovych-aplikaci-explicitni-resources.aspx

    pro WinForms je to obdobné. Delegáty tam nikde nepotřebujete.

    Stejnětak pro ostatní centralizované nastavení si myslím, že není běžný scénář motat do toho delegáty.



    Ano, to je všechno moc hezké, ale jde mi o přepnutí za běhu. Předpokládám, že v aplikaci pro Windows (nikoliv ASP) se v InitComponents prostě vygeneruje něco jako bTlacitko.Text = GetResourceString("KlickProTextTohoTlacitka"). Když změním jazyk, tak se ale nezmění text již vytvořených komponent, je v podstatě třeba zavřít úplně všechno, uložit a více méně spustit každé okno znovu, nebo ne?

    A nebo si to hold napsat, centralizovat a u každé komponenty si pamatovat onen klíč, držet spoják a v protected metodě SettingsChanged(...) dělat totéž co v InitComponents ohledně lokalizace.
    čtvrtek 10. ledna 2008 8:30

  •  Robert Haken napsal:

    Lokalizace v .NET se zpravidla odehrává na úrovni resources a jejich volba se řídí přepnutím příslušného Threadu do příslušné Culture, pro ASP.NET viz např.

    http://knowledge-base.havit.cz/asp-net/Lokalizace-webovych-aplikaci-explicitni-resources.aspx

    pro WinForms je to obdobné. Delegáty tam nikde nepotřebujete.

    Stejnětak pro ostatní centralizované nastavení si myslím, že není běžný scénář motat do toho delegáty.



    Ano, to je všechno moc hezké, ale jde mi o přepnutí za běhu. Předpokládám, že v aplikaci pro Windows (nikoliv ASP) se v InitComponents prostě vygeneruje něco jako bTlacitko.Text = GetResourceString("KlickProTextTohoTlacitka"). Když změním jazyk, tak se ale nezmění text již vytvořených komponent, je v podstatě třeba zavřít úplně všechno, uložit a více méně spustit každé okno znovu, nebo ne?

    A nebo si to hold napsat, centralizovat a u každé komponenty si pamatovat onen klíč, držet spoják a v protected metodě SettingsChanged(...) dělat totéž co v InitComponents ohledně lokalizace.



    Přepnutí za běhu - stačí si uvědomit, že při odbavování každého requestu se vykonává životní cyklus celé stránky znovu, tedy včetně nastavení vlastností Text z resources. Stačí tedy na začátku životního cyklu requestu (stránky) přepnout currentThread.UICulture a je to. Viz ten můj článek, opravdu je to tam popsané.

    Robert Haken, Microsoft MVP ASP/ASP.NET, HAVIT, s.r.o., www.havit.cz, http://knowledge-base.havit.cz
    středa 18. února 2009 21:00
    Moderátor