Feature detection .NET 4.5-ben

Ahogy januárban már írtam róla, az új 4.5-ös .NET Framework verziószáma (nagyjából) pontosan meg fog egyezni a 4.0 verziószámával, azaz in-place upgrade történik. (Hogy ez mennyire jó ötlet, arról még mindig lehet szavazni a januári cikk végén.) Akkor azt fejtegettem, hogy ez milyen problémákat fog felvetni, amikor a 4.0-ra tesztelt alkalmazásaink észrevétlenül 4.5-ön kezdenek el majd futni.

Na de most nézzük a fordított irányt. Íme az alábbi kiváló kódom, amit Visual Studio 11 alatt készítettem, .NET 4.5-re fordítva:

  static void Main(string[] args)
  {
    Console.WriteLine("Elindult.");
    Console.WriteLine("Vége.");
    Console.ReadLine();
  }

Kiválóan fut Windows 8-on. A lefordított EXE-t átviszem egy másik gépre, ahol nincs .NET 4.5 és ott is kiválóan fut! Nosza, használjunk valami spéci 4.5 feature-t:

  static void Main(string[] args)
  {
    Console.WriteLine("Elindult.");
    Console.WriteLine("Méret: " + GetSize().Result );
    Console.WriteLine("Vége.");
    Console.ReadLine();
  }

  private static async Task<int> GetSize()
  {
    WebClient wc = new WebClient();
    string content = await wc.DownloadStringTaskAsync(
new Uri(@"http://www.msdnkk.hu")); return content.Length; }

Ez .NET 4.5 híján is vidáman elindul, de futás közben elszáll:

W:\System\Desktop>VersionTest.exe
Elindult.

Unhandled Exception: System.TypeLoadException: Could not load type 
'System.Runtime.CompilerServices.IAsyncStateMachine' from assembly 
'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
  at VersionTest.Program.GetSize()
  at VersionTest.Program.Main(String[] args)

Ez már nagyobb gond, hiszen senki sem szereti a futási idejű hibákat. Ha ez így van, akkor mégis mire jó a Project Properties ablakban a Target Framework opció?

project-properties

Ha átállítod:

[assembly: TargetFramework(".NETFramework,Version=v4.5", 
           FrameworkDisplayName = ".NET Framework 4.5")]
  • Az app.config fájlban megváltozik a supportedRuntime elemben az sku attribútum értéke (webalkalmazás esetén a compilation elemben a targetFramework attribútum értéke):
<?xml version="1.0"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
  </startup>
</configuration>

Vajon melyiket figyeli a runtime? A fenti példából egyértelműen látszik, hogy a .config fájlt. Ha nincs ott a konfig fájl, elindul az alkalmazás, és majd futási időben száll el. Ha ott van a konfig fájl, akkor el sem indul:

download45

Itt a Yes-re kattintva jelenleg a .NET Framework 4.5 Beta letöltése kezdeményezhető a Microsoft Download Centerből.

Próbáljuk elkerülni a futási idejű hibát, azaz próbáljuk kitalálni futási időben, hogy milyen verzión futunk. A hagyományos megközelítés a verziószámok lekérdezése az Environment.Version tulajdonságon keresztül. Az eredmény:

  • 4.0: 4.0.30319.544
  • 4.5: 4.0.30319.17379

Szóval sem a major, sem a minor, sem a build verziószámra nem támaszkodhatunk, legfeljebb a revisionre. Arról pedig nem tudunk semmit, tehát a “nagyobb, mint 17000” jellegű megközelítések elég kockázatosak (még ha működnek is jelenleg).

Vessük be a JavaScriptből már jól ismert feature detection megközelítést, azaz ne a verziószámot ellenőrizzük, hanem azt tudjuk meg, hogy a funkció, amit használni akarunk, támogatott-e:

private static bool IsAsyncSupported()
{
  return Type.GetType("System.Runtime.CompilerServices.IAsyncStateMachine", 
false) != null; }

Majd:

if(IsAsyncSupported())
{
  Console.WriteLine("Méret: " + GetSize().Result);
}
else
{
  Console.WriteLine("Frissíts 4.5-re!");
// Vagy ugyanez a funkció async nélkül megvalósítva...
}

Ez működik, de biztos, hogy ezt akarjuk?

Gyanítom, hogy lesznek ebből kellemetlenségeink. Íme egy kedves példa: most akkor a webalkalmazásunk milyen .NET verzión is fut (a .NET Framework version listában nincs is 4.5):

iis-apppool-versions

 

Technorati-címkék: ,,,

One thought on “Feature detection .NET 4.5-ben

  1. nyelvész

    A példaprogramok végére miért jó odatenni a Console.ReadLine()-t?
    Sose értettem…
    Miért jó ennyit gépelni azért, hogy ne záródjon be a parancssor ablaka? Nem egyszerűbb nyomni Ctrl+F5-öt, vagy odarakni a helyére egy töréspontot?

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s