A következő címkéjű bejegyzések mutatása: C#. Összes bejegyzés megjelenítése
A következő címkéjű bejegyzések mutatása: C#. Összes bejegyzés megjelenítése

2009. március 24., kedd

Kép vagy állomány letöltés adott URL mögül

Nemrég szükségem volt a tárgybelire és szokás szerint ismét nem ugrott be elsőre a megoldás.
Gyanítom, hogy más is így lehet ezzel, tehát a magam és minden hozzám hasonlóan feledékeny olvasó számára most lejegyzem a dolgot.
 System.Net.WebClient objWebClient = new System.Net.WebClient();
 objWebClient.DownloadFile(URL, FILENAME);
 System.Drawing.Image imgPhoto = System.Drawing.Image.FromFile(FILENAME);

Esetleg van másféle megoldás is?

2008. november 23., vasárnap

Levélküldés tesztelése SMTP nélkül

A legtöbb webes alkalmazásban van egy-két olyan sztori, amikor levelet szándékozunk kiküldeni a rendszerből. A végleges változatban általában SMTP szerver felhasználásával tesszük ezt, de fejlesztés közben meglehetősen kényelmetlen minden tesztfuttatás alkalmával ellenőrizni egy postaládát. Ráadásul korántsem biztos, hogy rendelkezésre áll a megfelelő szerver, a fejlesztői gépre sem feltétlenül tudunk vagy akarunk telepíteni.
Ilyenkor az SmtpClient osztály beállításával megtehetjük, hogy a saját fájlrendszerünkkel "levelezünk".
Fentiekhez a web.config állományban a következő beállítások szükségesek:

<system.net>

<mailSettings>

<smtp deliveryMethod="SpecifiedPickupDirectory">

<specifiedPickupDirectory pickupDirectoryLocation="c:\temp\mailpickup"/>

</smtp>

</mailSettings>

</system.net>


Így azonnal ellenőrizhetjük, hogy az üzenet a megfelelő tartalommal előállt-e.

[Test]

public void SendMailTest()

{

SmtpClient smtpclt = new SmtpClient();

MailMessage message = new MailMessage("from@server.com", "to@server.com");

message.Body = "Body";

message.Subject = "subject";

smtpclt.Send(message);

}


A kliensnek egyébként futás közben is megmondhatjuk, hogy a levelet ebbe a könyvtárba küldje:

smtpclt.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;

smtpclt.PickupDirectoryLocation = "c:\\temp\\mailpickup";

2008. október 29., szerda

Egymásba ágyazott generikus listák

Meglepő, de lehetséges:

Ebben a postban illetve az egyik kommentjében van egy szép példa

204 List<List<int>> MyListOfIntLists;

205 myListOfIntLists = new List<List<int>> {

206 new List<int> { 1, 2, 3 },

207 new List<int> { 4, 5, 6 },

208 };


2008. szeptember 5., péntek

Hosszú elérést röviden

Ismét sikerült felfedeznem egy hasznos apróságot a C#-ban.
Velem együtt valószínűleg többen dolgoztak már úgy, hogy egyszerre használták pl a

System.Drawing.Drawing2D

és a

System.Web.UI.WebControls

névtereket.

Ilyenkor, ha egyik vagy másik helyről szeretnénk az Image objektumot használni, akkor kénytelenek vagyunk végigkalapálni az objektum teljes nevét névterestül, mindenestül.

Ez intellisense-el nem olyan nehéz, de mégiscsak munkás, meg hát nem is szép. Például:
System.Drawing.Drawing2D.Image im = new System.Drawing.Drawing2D.Image();
Ilyen esetekben hasznos lehet a névterekre illeszthető alias, amit az alábbi módon használhatunk:

using Draw = System.Drawing.Drawing2D;
Draw.Image im = new Draw.Image();

Így azért csak rövidebb :)

2008. július 16., szerda

Geocimkézés .NET-ben

Érdekes és hasznos bejegyzést találtam a geotagging témában.
Roiy Zysman ebben a cikkben általánosan írja le a geotagging lényegét, de ami ennél fontosabb egy kis gyakorlati kóstolót is közöl arról, hogyan is tudunk GPS koordinátákkal és egyéb metaadatokkal ellátni egy jpeg képet.
A geotaggingra már a magyar WIKIben is van szócikk, akinek ez a szó nem mond semmit itt utána nézhet.
Programozói szempontból közelítve a dolgot a lényeg, hogy az EXIF adatok írására és olvasására a System.Drawing.Image osztály tökéletesen felhasználható.
Egy a cikkben szereplő rövid, egyszerű kódrészletet szépen megvilágítja a lémyeget:
Image Pic = Image.FromFile(Filename);
PropertyItems = Pic.PropertyItems;
PropertyItems[0].Id = 0x0002; //index of the EXIF TAG
PropertyItems[0].Type = 5;//
PropertyItems[0].Len = length;
PropertyItems[0].Value =new byte[length];
Pic.SetPropertyItem(PropertyItems[0]);
Az úr volt oly kedves és egy statikus függvényt is készített számunkra, hogy könnyedén tudjuk GPS koordinátákkal ellátni akár saját alkalmazásunkban is akár a JPG állományokat.

2008. május 27., kedd

Újabb ingyenes e-book .NET témában

Bár inkább cikkgyűjteménynek nevezhető, ami a Simple-Talk közösségi szájt néhány írását fogja egybe. Bár ha jól sejtem elsődlegesen a marketing célokat szolgált a gyűjtemény létrehozása, illetve közzététele, de ettől függetlenül rendkívül hasznos anyagnak tűnik első blikkre. Olyan problémák kerültek be a válogatásba, amik közül jó esélyyel legalább egyeel minden ASP.NET-tel foglalkozó fejlesztő találkozott már.
Letölthető innen.

2008. május 15., csütörtök

Fájlműveletek tesztelése

A piszkozatok között kallódott egy marék forráskód, megnézegettem mi lehetett ez.
Nos hát...
Egy időben problémám volt az egységteszteléssel fájlokat használó metódusok esetén, erre találtam egy megoldást. Lehet, hogy van ennél jobb is, de a célnak megfelelt.
Bár ha jobban belegondolunk lehet róla vitatkozni, hogy egységtesztelésről vagy inkább integrációs tesztről van-e szó, hiszen a programunknak a fájlrendszerrel való együttműködését teszteljük. De a talált maréknyi kód szempontjából ez nem is érdekes :)

Az alkalmazás valami képeket méretezett és nevezett át, aztán lementette az átméretezett képeket.

A probléma ott volt, hogy úgy lehessen tesztelni, hogy lehetőleg ne kelljen semmi spéci beállításokat csinálni, ne kelljen rendszergazdai jog stb., de a tesztállományokat kiírni, majd a futás végén letörölni gond nélkül tudjam bármelyik gépen. A program a DirectoryInfo osztályt használta, amit az én szintemen lehetetlennek tűnt mockkal vagy bármi más módon kiváltani. Így jött az ötlet, hogy az aktuális felhasználó profilja alatti temp könyvtárba fogom pakolni az tesztállományaimat. A temp könyvtár elérését a  .NET prímán támogatja, a Path osztályon keresztül.

DirectoryInfo d = new DirectoryInfo(Path.GetTempPath());

A Path osztály további finomságokkal is szolgál, például elegánsan fűzhetünk össze vele útvonalakat. Ráadáasul ha ezt a módszert szokja meg az ember, akkor elvileg MONO alatt azonnal fordíthatja a kódját, nem lesz probléma az oprendszerek különböző szeparátoraival. (Azért mondom, hogy elméletben, mert ezt én még sosem próbáltam, de működnie kellene.)

DirectoryInfo d2 = new DirectoryInfo(Path.Combine(d.FullName, "backup"));

A teszteléshez használt fájlokat egyszerűen resource-ként belefordítottam a tesztprogramba, így már szépen létrehozhatom a tesztállományaimat a teszt indításakor:


        [TestFixtureSetUp]

        public void SetUpDir()

       {

            ...

            ...

            ...

            TestResource.Image1.Save(Path.Combine(d2.FullName "23817_2_01.jpg"));

            TestResource.Image1.Save(Path.Combine(d2.FullName, "23817_2_02.jpg"));

            ...

            ...

            ...

        }

A teszt után pedig, visszaállítandó az eredeti állapotot törölhetem a tesztállományokat. A megoldás nem túl szofisztikált, de a célnak megfelel, tesztelni lehet a programot. Ha valaki tud erre jobb megoldást írja meg ;)

2008. május 12., hétfő

Visual Studio 2008 és .NET Framework 3.5 SP1 Beta

Ma reggel jött ki a fent említett SP1 szervízcsomag bétája, olyan friss, hogy még meleg.
A csomagban sok WPF-es javítás van, a WCF-fen is reszeltek valamit.
Véleményem szerint a két legfontosabb újdonság a teljes SQL2008 support (eddig ehhez kellett egy kiegészítő), illetve a sokak által kíváncsian várt Entity Framework, mégpedig a VS-be integrált kattogós dizájnerrel karöltve. Állítólag a JS szerkesztőn is javítottak, ami azt illeti ezen van is mit és bekerült valami, aminek pár éve még nagyon örültem volna, mégpedig a klasszikus ASP intellisense támogatás.
ScottGuthrie egy bejegyzésben szépen összeszedte az újdonságokat, ajánlatos átfutni.
Még alig kezdtem el felrakni a pakkot máris vidám pillanatokat szerzett nekem a .NET FW telepítője :)

2008. április 9., szerda

Hatékonyságnövelő tippek a Visual Studio 2008-hoz

Az egyik MSDN blogban megjelent egy bejegyzés, 10 tippel, ami a kódolás hatékonyságát növelheti Visual Studioban.
Ki ne szeretne hatékonyabb lenni, hát átolvastam, itt most továbbadom, a saját véleményemmel kiegészítve. Amit jónak tartok így jelölöm: (!), amit nem azt így (?), ahol ezek a jelek nem szerepelnek azt döntsd el magad :)

1. tipp: Tanuld meg a gyorsbillentyűket.

Ez nem túl fantáziadús javaslat, mondhatnám, hogy triviális, de tény ami tény, valóban hatékonyságnövelő tényező, ezért is hívják úgy, hogy GYORSbillentyű.
A legfontosabbakat felsorolja a cikk, bár SZVSZ ezeket mindenki ismeri, hacsak nem ma látott először Studiot.
  • Build: CTRL + SHIFT + B
  • Word completion: CTRL + SPACE
  • Start with debugging: F5
  • Start without debugging: CTRL + F5
2. tipp: Automatikus dokumentációgenerálás GhostDoc segítségével (?)
Ez a tipp erősen vitatható. Egyetlen esetben van értelme használni, ha valaki olyan cégnél dolgozik, ahol a dokumentációt "kilóra" mérik. Ugyanis egyedül ilyen esetben csinál épeszű ember ilyen "dokumentációt":

Vagy ilyet:
A magam részéről úgy gondolom, hogy ennek semmi értelme. Ugyanis a függvény, property, osztály neve ha "önleíró", mint fent, akkor gyakorlatilag csak szószaporítás az ilyen típusú dokumentáció, ha azonban nem az, akkor semmilyen automatikus eszköz nem tudja értelmesen dokumentálni, csak a programozó.

3. tipp: Használd az automatikus tulajdonságokat
Ezt én inkább így írnám:
Használd ki a nyelvi újdonságokat (!)

Az automatikus tulajdonságok egy hasznos újítás a C# 3.0-ban. Mindenkit bátorítanék ennek az anyagnak az átolvasására, aki még nem tette, itt minden újdonság, szépen jól magyarul olvasható el.
A hatékonyságnövelő újdonságok bajuszokban, rövid példával:

Automatikus tulajdonságok


Új lehetőség az objektumok inicializálására



Lokális típusfeloldás


Lambda kifejezések


Erről itt írtam egy szemléletes példát.

4. Tipp: Használd a Refactort

Ha nem tudsz vagy nem akarsz automatikus tulajdonságot alkalmazni, hasznos lehet a Refactor menü Encapsulate field... menüpontja.
Így kezded:


..és ez lesz belőle:

A Rename is igen hasznos lehet, bár néha igen lassúcska, illetve kétségtelenül hasznos és (általam) gyakran használt tool az Extract interface..., ami nem meglepő módon interfészt állít elő az osztályunk alapján pikk-pakk módon.

Az 5. tipp (egyéni parancsok) részben emlegetett PowerCommands toolt ki fogom próbálni, mert a projekt oldalán látok néhány ígéretes dolgot (Copy/Paste Class, Copy/Paste References).

6. tipp: a build testreszabása

Egy nagyobb projekt esetében perceket vehet el az életünkből fölöslegesen, ha olyan dolgok is be vannak kapcsolva a projekt fordítása során, amelyekre például csak a végső változatban lesz szükség. Példaként a post az XML dokumentáció generálását hozza. Érdemes ezekre odafigyelni.



7. tipp: használd a VS unit test generáló funkcióját (??)

Hát ez nálam erősen kérdőjeles. Nem tudom mennyit ér egy ilyen automatikusan generált teszt. Érzésem szerint ez ugyanaz a kategória, mint a fentebb tárgyalt automatikus dokumentálás, vagyis csak kilóra van haszna, érdemben nem nagyon. Emgem ez azért sem érint különösebben, mert az NUnit és a Testdriven.NET használata mellett köteleztem el magam egyelőre, így a VS saját teszteszközeit nemigen használom.

A következő két tipp valóban hasznos, azonban a C#-hoz, de főleg a Studiohoz társítani némileg erős, hiszen mindkettő iknább módszertani kérdés, bár a szükséges eszközök valóban rendelkezésre állnak VS2008-hoz, ha másképp nem, hát külső fejlesztésként.

8. tipp: Interfész-központú tervezés

Az interfész alapú tervezés az én olvasatomban az agilis módszertanok fegyvertárába tartozik. A cikk arra mutat rá, hogy ennek a módszernek jelentős hatékonyságnövelő hatása lehet, főleg teamek esetében. A lényeg röviden annyi, hogy a többrétegű alkalmazások fejlesztésekor legelőször a kommunikációs felületek kialakítása a célszerű, mert így a csapat tagjainak nem kell egymásra várniuk, hiszen például az üzleti logika készítői elkészíthetik a saját - nyilván egyszerűsített - adathozzáférési objektumaikat vagy a következőben emlegetett mocking technikát alkalmazhatják, így párhuzamosan tud zajlani a fejlesztés szorosan kapcsolt rendszer esetében is. Jah igen, ami a Visual Studiot illeti, az objektumtervező lehetőséget ad minimális erőfeszítéssel az interfészek előállítására



9. tipp: A függőségek kiiktatása mock objektumok segítségével

A tipp kétségtelenül hasznos, bár ez nem a Studio vagy a C# fejlesztőinek érdeme :)
Mivel jómagam is newbie vagyok a tesztvezérelt fejlesztésnek nevezett metodológiában, ezért nem szeretnék itt mélyen belemenni a dolog taglalásába. A lényeget már majdnem le is írtam az előző pontban. Gyakorlatilag arról van itt szó, hogy az álobjektumokat egy eszköz segítségével úgy állítjuk elő, hogy azok megvalósítsák azokat a függvényeket, tulajdonságokat, amelyeket a tesztek során használni szeretnénk (lehetőség szerint CSAK azokat). Így egyrészt valóban függetlenítjük a programrészünket a többitől, másrészt a tesztjeink jelentősen gyorsulhatnak is, ha ezzel a módszerrel kiiktatunk például adatbázisműveleteket vagy más idő és erőforrásigényes eljárásokat. A cikk írója által ajánlott rendszer a RhinoMocks névre hallgat, jómagam is ennek használatába kezdtem bele a közelmúltban, az elterjedtsége és nem utolsó sorban az ingyenes volta miatt.
A cikk szerzője hoz egy rövid példát is, amit idelinkelek:



10. tipp: Adatvezérelt egységtesztek

Ismét röviden arról van itt szó, hogy X darab teszt írása helyett egyetlen tesztet írunk, amelyet a VS segítségével egy adatbázis X sorára lefuttathatunk. Ez a tesztek írását valóban gyorsítja, ellenben a futtatáskor - az előző pontban írottal szemben - éppen, hogy megterhetljük a tesztet egy kvázi fölösleges adatbázis és/vagy fájlolvasással. Én kis adatmennyiség esetében (és hogy ne kelljen megválnom a jó öreg NUnittól ;)) inkább az NUnit egyik kiegészítőjét használom (RowTest Extension for NUnit). Ki-ki döntse el, hogy melyiket akarja szeretni.

2008. április 2., szerda

Quick-n-dirty megoldás tömb rendezésére Lambda kifejezéssel

A napokban egy könyvtárban együtt levő fájlokkal kellett dolgoznom. Ha nem csak a fájlnevekre van szükségünk, akkor ennek legegyszerűbb módja a DirectoryInfo objektum GetFiles metódusának használata.

private DirectoryInfo mPictureDir;
....
....
FileInfo[] fileEntries = mPictureDir.GetFiles(mSearchPattern);
Igen ám, de ez a tömb egyáltalán nem biztos, hogy a nekünk megfelelő módon rendezett, így rászorolunk az Array.Sort használatára. Jelen esetben név szerint szeretném rendeznia tömböt.

Mit is csináltunk korábban egy C# 2.0-át használó alkalmazásban?
Array.Sort(fileEntries, delegate(FileInfo x, FileInfo y)
{
return x.FullName.CompareTo(y.FullName);
});
Ez a C# 3.0 alatt a lambda kifejezések jóvoltából valóban QUICK módon leírható:

Array.Sort(fileEntries,(x,y) => x.FullName.CompareTo(y.FullName)) ;
Hasznos kis jószág ez, hiába...
A lambda kifejezéseknek már magyarul is van némi irodalma.

2008. március 26., szerda

Image objektum fájlból: hogyan és hogyan ne....

A .NET Framework System.Drawing névterében levő Image objektum nagyon megkönnyíti képekkel történő alapvető műveletek végzését. Amennyiben nem mi állítjuk elő a képet, hanem a fájlrendszerből kell felolvasni, akkor erre több módszer is létezik, de nem minden esetben megfelelő a legkézenfekvőbb megoldás.

Készítettem egy móricka osztályt a szemléltetéshez. A célom, hogy a képet egy másik könyvtárba mozgassam vagy átnevezzem, előtte és utána meg ezt-azt csinálgassak vele, valahogy így:
class Program
{
static void Main(string[] args)
{
if (args.Length > 0)
{
ImageLoader loader = new ImageLoader();
loader.ImagePath = args[0];

//Load image
...
...

//do something terrible
...
...
loader.MoveImage(args[1]);
...
...
//do something terrible
}
else
Console.WriteLine("Add meg a forrast es a celt");
}
}

Csinálok is gyorsan egy osztályt, a megfelelő metódusokkal és természetesen a szükséges egységteszttel.



///
/// Minta az Image objektum létrehozására fájlból.
///

class ImageLoader
{
...
...

///

/// Kép felolvasása FromFile metódussal
///

public void SetImageWithFromFile()
{
ImageToLoad = Image.FromFile(ImagePath);
}

...
...
public void MoveImage(string destination)
{
File.Move(ImagePath, destination);
ImagePath = destination;
}
}

[TestFixture]
public class ImageLoaderTest
{
string originalpath;
string testpath;
...
...

[SetUp]
public void CreateTestData()
{
...
...
}

///
/// Az átnevezés tesztelése FromFile metódussal
///

[Test]
public void FromFileTest()
{
ImageLoader loader = new ImageLoader();
loader.ImagePath = originalpath;
loader.SetImageWithFromFile();
loader.MoveImage(testpath);

Assert.That(File.Exists(testpath) && (!File.Exists(originalpath)));
}

[TearDown]
public void DeleteTestData()
{
...
...
}

No lássuk mi történik...

Azt a hétlövetű kukoricacsövit neki! Hát ez bizony elesett....
Aszongya:

TestCase 'ImageLoader.ImageLoaderTest.FromFileTest'
failed: System.IO.IOException : A folyamat nem éri el a fájlt, mert már másik folyamat használja.

Hm. Mit is mond a help erről a metódusról?
Aszongya:

The file remains locked until the Image is disposed.

Jaj-jaj-jaj. Most mit tegyek, hisz nem akarom dispose-olni, mert nekem az még kell és különben is...
Ha memóriában dolgozék akár jó is lehetne a dolog...



class ImageLoader
{
...
...

///
/// Kép felolvasása stream segítségével.
///

public void SetImageWithStream()
{

byte[] imagebytes = File.ReadAllBytes(ImagePath);
MemoryStream ms = new MemoryStream(imagebytes);
ImageToLoad = Image.FromStream(ms);
}

...
...
}

[TestFixture]
public class ImageLoaderTest
{
...
...

[SetUp]
public void CreateTestData()
{
...
...
}

///
/// Átnevezés FromStream metódussal
///

[Test]
public void FromStreamTest()
{
ImageLoader loader = new ImageLoader();
loader.ImagePath = originalpath;
loader.SetImageWithStream();
loader.MoveImage(testpath);

Assert.That(File.Exists(testpath) && (!File.Exists(originalpath)));
}

[TearDown]
public void DeleteTestData()
{
...
...
}

Mit is mond a Saga a ReadAllBytes -ról?
Opens a binary file, reads the contents of the file into a byte array, and then closes the file.
Na akkor most, nincs nyitott fájlom, van viszont egy Image objectem amivel azt csinálok amit csak akarok, a memorystreamtől pedig ráérek megszabadulni, amikor mindent befejeztem vagy rábízom a szemétgyűjtőre.