Pokazywanie postów oznaczonych etykietą AroLibraries. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą AroLibraries. Pokaż wszystkie posty

niedziela, 3 marca 2013

Dziedziczenie w c#

Co jakiś czas napotykam na problemy związane z Co- i Contra- wariancją, więc postanowiłem troszkę pobawić się z .NETem. Chciałbym przedstawić dlaczego jest z tym taki problem. Niech poniższy wpis będzie wstępem do większego zagadnienia.
Stwórzmy 2 klasy. Jedna (B) będzie dziedziczyła po drugiej (A)
class A
{
}
 
class B : A
{
}

Aby poprawić czytelność stwórzmy extension method, która będzie określała czy jeden typ dziedziczy od drugiego typu:
 public static class TypeExt
{
 public static bool IsFromType<T>(this Type type)
 {
     return typeof(T).IsAssignableFrom(type);
 }
}

Teraz możemy sprawdzić co zwróci nam ta metoda.
     Console.WriteLine(typeof(A).IsFromType<A>()); //true 
     Console.WriteLine(typeof(B).IsFromType<A>()); //true 
     Console.WriteLine(typeof(A).IsFromType<B>()); //false 

Sprawdzamy jak będzie dla typów generycznych.
 Console.WriteLine(typeof(List<B>).IsFromType<List<B>>()); //true
 Console.WriteLine(typeof(List<B>).IsFromType<IEnumerable<B>>()); //true

Typy generyczne są tak samo traktowane jak 'normalne' typy. Ale co będzie, kiedy argumenty w typach generycznych będą różne lub jeden argument będzie dziedziczony po drugim??
    Console.WriteLine(typeof(List<B>).IsFromType<List<A>>()); //false

Nawet jeżeli typ generyczny będzie taki sam, argumenty w typie generycznym będą inne, ale w relacji dziedziczenia to nie ma zależności. Wtedy musimy porównywać argumenty tych typów generycznych.
public static bool IsGenericArgFromType<T>(this Type type)
{
   var args1 = typeof(T).GetGenericArguments();
   var args2 = type.GetGenericArguments();

   return args1.Length == args2.Length &&
      args1.Zip(args2, (arg1, arg2) => new { arg1, arg2 })
      .All(x => x.arg1.IsAssignableFrom(x.arg2));
}

Console.WriteLine(typeof(List<B>).IsGenericArgFromType<List<A>>()); //true
Console.WriteLine(typeof(List<string>).IsGenericArgFromType<List<object>>()); //true
Pomimo tego, że argumenty w typie generycznym są w relacji dziedziczenia (przyporządkowania) to te dwa type nie są przyporządkowane do siebie. Taki sam problem jest, gdy mamy listę stringów i listę obiektów. W naturalny sposób lista stringów powinna być przyporządkowana do listy obiektów, ale tak nie jest.

środa, 7 marca 2012

Jak przyspieszyć kodowanie cz.3 ( AroLibraries )

Od ponad 2 lat rozwijam projekt (AroLibraries) w którym zapisuje wszystkie metody rozszerzalne ( extension methods ).


AroLibraries to biblioteka zawierająca rozwiązania, które są pomocne przy wytworzeniu oprogramowania. Jednym z podstawowych rozwiązań to wykorzystanie rozszerzonych metod. Takie rozwiązanie pozwala na: - ukrycie części implementacji - czytelniejszą składnię - wielokrotne wykorzystanie tego samego kodu
Zamiast za każdym razem pisząc:
    Bitmap image = new Bitmap("picture.bmp");
    Stream memoryStream = new MemoryStream();
    image.Save(memoryStream, ImageFormat.Bmp);
    byte[] bytes = new byte[memoryStream.Length];
    memoryStream.Position = 0;
    memoryStream.Read(bytes, 0, (int)memoryStream.Length);
    
    memoryStream.Close();
    var binary = new Binary(bytes);
   return binary;

Możemy zapisać w formie:
    Bitmap image = new Bitmap("picture.bmp");
    image.ToBinary();
Kod z wykorzystaniem extension methods jest zdecydowanie czytelniejszy. Poniżej przedstawiam parę ciekawszych rozwiązań za pomocą AroLibraries:
9.8F . IsBetween(9, 10); 
//określa czy liczba 9.8 jest w przedziale 9 i 10

DateTime.Now.IsWeekend(); 
// sprawdza czy dzisiaj jest weekend

DateTime.Now.ToSecondsFromEpoch(); 
// data w formacie Epoch

DateTime.Now.EqualsToHour(new DateTime(1986, 03, 29, 12, 0, 0));  
//sprawdza czy teraz jest ta sama godzina

"4AAB7F67-A898-442a-884A-364411D584EC".IsValidGuid();
 //sprawdza czy string jest w formacie GUDI

"mymail@zzzzzzz.com". IsValidEmailAddress(); 
//sprawdza czy string jest w formacie e-maila

string words = "Some words about Library";
words.Reverse(); 
// odwraca string  ("yrarbiL tuoba sdrow emoS")

words.GetRightSideOfString(13); 
// zwraca prawą stronę stinga "about Library"

words.CountWords(); 
//liczy wyrazy

words.ReplaceOnce("a",""); 
//zamienia tylko pierwsze wystąpienie w tekście

words.ToMd5(); 
//zwraca skrót MD5 z tekstu


new Exception("0", new Exception("1", new Exception("2", new Exception("3"))))
. GetMostInner(); 
//zwraca najbardziej wewnętrzny wyjątek  (Exception nr "3")

var numbers = 1.IterateTo(10);
//iteruje od 1 do 9 

numbers.IndexOf(6); 
//zwraca index liczby 6
numbers.Repeat(2, true); 
//{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9}

numbers.Repeat(2, false); 
// {1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9}

numbers.Shuffle();
 //miesza elementy

numbers.Swap(1,2); 
//zamienia miejscami element nr 1 z elementem nr 2

numbers.ToString(";");
 // zwraca string elementów oddzielonymi średnikiem ( "1; 2; 3; 4; 5; 6; 7; 8; 9")


9.In(numbers); 
//sprawdza czy liczba 9 jest w danej kolekcji

9.ToMonthName("Styczeń");
 //zwraca nazwę miesiąca

'a'.IsVowel(); 
//sprawdza czy jest samogłoską

var persons = new[]
{
new Person {
           FirstName = "Arek", 
           LastName = "XYZ",
           Age = 26},
};
persons.ToDataTable();    
// zmienia kolekcje w tabelę

persons.OrderBy(x => x.Age); 
//sortuje po danym polu


Bitmap image = new Bitmap("picture.bmp");
image.ToBinary();  
//konwersja do typu Binary

image.SaveJpeg("pic.jpg"); 
//zapisuje do formatu jpeg

image.Fill(Color.Black);
 //zwraca obrazek cały pomalowany na czarno

image.IsPixelInImage(-1, 100); 
// sprawdza czy można pobrać pixel o podanych współrzędnych  

image.GetPixels(); 
// zwraca wszystkie kolory na obrazku

image.ToByte(); 
//konwersja do byte[]

image.ToByte().OpenBytesAsFile(".bmp"); 
// otwiera plik w zewnętrznym edytorze


TextBox tb= new TextBox();
tb.WriteLine("Text"); 
//pisze po textboxie

DirectoryInfo di= new DirectoryInfo("c:");
di.GetDirectorySize(); 
//zwraca wielkość katalogu

Stream stream= GetStream();
stream.SaveToFile("Text.txt"); 
//zapisuje stream do pliku

Stream textStream= new MemoryStream();
stream.CopyStreamTo(textStream); 
//kopiuje do nowego źródła
           

XmlNode node = GetXmlNode();
node.ToXElement(); 
//zwraca XElement

Projekt jeszcze nie jest w pełni stworzony. W przyszłości będę chciał stworzyć do niego testy jednostkowe. Liczne extension methods można znaleźć pod tym linkiem, a kod źródłowy projektu można pobrać z portalu codeplex.

środa, 30 marca 2011

Co z tymi pakietami (NuGet on Visual Studio)

Jedno z najpiękniejszych cech Visual Studio 2010 jest możliwość dodawania bibliotek do projektu za pomocą komend. Dlatego też bardzo spodobał mi się dodatek NuGet.

W poniedziałek (28.03.2011) miałem prezentacje o NuGet.
Do testów Nugeta wykorzystałem moje pakiety. Pierwszy z nich była biblioteka z metodami rozszerzającymi AroLibraries , gdzie można ją również znaleźć na codeplexie.
A druga paczka to PDFLittleSigner - mała paczka do podpisywania PDFów.

View more presentations from arekbee

Nie była to typowa prezentacja, gdyż starałem się wiele rzeczy napisać, a nie przedstawiać już gotowego kodu czy filmiku, gdzie bezbłędnie wszystko działa.

Na myśl przychodzą mi słowa Scott Hanselman który mówił że na prezentacji przy pisaniu kodu powinno się parę razy pomylić w oczywistych miejscach, bo dzięki temu wiem czy słuchacze śledzą to co robimy.

czwartek, 23 września 2010

AroLibraries

Pisząc kod bardzo często powtarzam tą samą sentencje kodu.
Wraz w c#3.0 pojawiły się extension methods, które ukrywają kod.
Standardowy przykład to zastosowanie konwersji z typu string na int.

string valueString="1";
int valueInt;
int.TryParse(valueString, out valueInt); // valueInt == 1


to zapisujemy w postaci:
string valueString="1";
valueString.ToInt(); // == 1

Kiedy nie podoba mi się zapis:
if(boolVariable == flase )

((details["Node"] as TreeNode).Parent as TreeNodeExt).Name

Przerabiam na bardziej czytelny:
if(boolVariable.IsFalse())

details["Node"] .As<TreeNode>()
.Parent .As<TreeNodeExt>() .Name

Ale to kwestia gustu :)

Extension methods mają duże zastosowanie w LINQ to Object
NP:
Aby mieć informacje o wszystkich plikach na dysku o podanym rozszerzeniu należy napisać troszkę kodu:

static void Main(string[] args)
{
string path = @"D:\";
DirectoryInfo dr = new DirectoryInfo(path);
FileCollection = new List<FileInfo>();
FillFilesInDirectories(dr);
}

private static List<FileInfo> FileCollection = null;
private static void FillFilesInDirectories(DirectoryInfo dir)
{
var dirs = dir.GetDirectories();
foreach (var vDir in dirs)
{
FileCollection.AddRange(vDir.GetFiles());
FillFilesInDirectories(vDir);
}
}



Lub za pomocą LINQ:

static void Main(string[] args)
{
string path = @"D:\";
var FileCollection = new DirectoryInfo(path)
.GetDirectories()
.SelectRecursive(x => x.GetDirectories()) //Rekurencja
.SelectMany(x => x.GetFiles()); //Pobieramy Pliki
}


Od razu widać, że kod w LINQu jest bardziej czytelny.

Projekt rozszerzający możliwości Extension Methods można pobrać ze strony AroLibraries