Enum – snippetów część pierwsza

Posted in Bez kategorii on Marzec 27th, 2011 by admin – Be the first to comment

Przy pracy z typami wyliczeniowymi często wykorzystuje się podobne fragmenty kodu, schematy (by nie rzec – wzorce projektowe), zatem postanowiłem je pozbierać – dla pamięci i na potrzeby przyszłych projektów.

1. Pętla oparta na wartościach typu wyliczeniowego:


enum TestEnumType { EnumValue1, EnumValue2, EnumValue3 };
static void Main(string[] args)
{
foreach (TestEnumType value in Enum.GetValues(typeof(TestEnumType)))
{
Console.Out.WriteLine(value);
}
Console.ReadLine();
}

2. Wartość liczbowa


enum TestEnumType { EnumValue1, EnumValue2, EnumValue3 };
static void Main(string[] args)
{
foreach (TestEnumType value in Enum.GetValues(typeof(TestEnumType)))
{
Console.Out.WriteLine((int)value);
}
Console.ReadLine();
}

3. Opisy wartości

Najpierw musimy sobie stworzyć klasę, która będzie zawierać extension methods. Zaczniemy od metody, która dla wartości enum zwróci wartość jej atrybutu Description (lub pusty string gdy ta wartość takiego atrybutu nie będzie miała zdefiniowanego):


public static class EnumExtensions
{
public static string ToDescriptionString<TEnum>(this TEnum val)
{
bool isEnum = val.GetType().IsEnum;
if (!isEnum)
throw new Exception("Parametr musi być enumeracją.");
DescriptionAttribute[] attributes;
attributes = (DescriptionAttribute[])val.GetType().GetField(val.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : string.Empty;
}
}

I wykorzystanie:


enum TestEnumType
{
[Description("Wartość początkowa")]
EnumValue1,
[Description("Wartość domyślna")]
EnumValue2,
[Description("Wartość dodatkowa")]
EnumValue3
};
static void Main(string[] args)
{
foreach (TestEnumType value in Enum.GetValues(typeof(TestEnumType)))
{
Console.Out.WriteLine(string.Format("{0}: {1}", value, value.ToDescriptionString()));
}
Console.ReadLine();
}

4. IsOneOf

Inną bardzo przydatną, nie tylko przy operacjach na typach wyliczeniowych, metodą jest:


public static bool IsOneOf(this T item, params T[] values)
{
return values.Contains(item);
}

I zastosowanie:

foreach (TestEnumType value in Enum.GetValues(typeof(TestEnumType)))
{
if (value.IsOneOf(TestEnumType.EnumValue1, TestEnumType.EnumValue2))
Console.Out.WriteLine(string.Format("{0} - Jest!", value));
}

Visual Studio – katalogi .svn

Posted in Bez kategorii on Luty 22nd, 2011 by admin – Be the first to comment

Czasem nagle w Solution Explorer pojawiają mi się katalogi .svn, losowo w różnych podkatalogach projektu. Chodzi oczywiście o projekty webowe. Na razie nie znalazłem przyczyny, ale dla potomności odnotowuję co zrobić by zniknęły – należy ustawić atrybut Hidden dla tych katalogów .svn.

Startupy – ciężki kawałek chleba

Posted in Bez kategorii on Grudzień 29th, 2010 by admin – Be the first to comment

Chyba nawet tworzenie startupu o startupach nie jest proste – chciałem poczytać o nowych pomysłach i startupach i po wejściu na kilka stron na ten temat okazało się, że wymierają… żadnych wpisów od kilku miesięcy, żadnych artykułów, nowych stron. Czyżby na naszym rynku działo się tak mało, że nie da się prowadzić strony o nowych serwisach?

User-Defined Data Types w SQL Server

Posted in Bez kategorii on Grudzień 25th, 2010 by admin – Be the first to comment

Na co dzień korzystam  z innych serwerów SQLowych, jednak coraz częściej przychodzi mi zmierzyć się z SQL Serverem. I w trakcie tych zmagań coraz częściej ten serwer mnie zadziwia.

Zatem zadziwienie nr 1 – dlaczego nie da się zmienić bazowego typu dla typu zdefiniowanego przez użytkownika? Dlaczego nie ma ALTER TYPE? Przecież brak takiej funkcji pozbawia użytkownika podstawowej zalety stosowania takich typów – możliwości łatwej zmiany typu jaki kryje się pod stworzonym przez użytkownika aliasem.

Przykład – mam w bazie kilka pól reprezentujących numer telefonu, pomyślałem sobie – stworzę sobie typ numertelefonu, który na razie będzie 20-znakowym napisem, a potem się zobaczy, może trzeba będzie to zmienić. No i dotarłem do momentu gdy faktycznie warto to zmienić, tylko… nie ma jak! To po co był mi ten typ numertelefonu? I tak, wg instrukcji znalezionych w sieci, będę musiał zlokalizować i modyfikować definicję wszystkich pól które korzystały z typu numertelefonu…

A może jednak jest jakaś sensowna metoda przewidziana przez Microsoft?

ASP.NET MVC – walidacja to nie tylko błędy, ale i ostrzeżenia.

Posted in Bez kategorii on Październik 7th, 2010 by admin – Be the first to comment

Tworząc swoją pierwszą aplikację w ASP.NET MVC natknąłem się na problem walidacji wprowadzonych w formularzu danych. Standardowo MVC dostarcza prosty mechanizm wspierający walidację – DataAnnotations oraz odpowiednich metod w wspierających kontrolę danych:

- Html.ValidationMessage – helper wyświetlający komunikaty błędów,

- ModelState.AddModelError – do „ręcznego” dodawania błędów,

Wszystko to dość dokładnie opisane jest w Internecie, np. tutaj.

Mi jednak w standardowym mechanizmie zabrakło ostrzeżeń – czyli komunikatów wskazujących użytkownikowi pewne problemy we wprowadzonych danych, ale pozwalające na zapis formularza po potwierdzeniu zapoznania się z tymi ostrzeżeniami.

Rozwiązanie które stworzyłem ma jeszcze wiele niedoskonałości i nie jest jeszcze tak eleganckie jak bym chciał, ale zaczyna się sprawdzać w praktyce i dlatego postanowiłem się nim podzielić.

Zacząłem od stworzenia klasy

public static class ModelWarningsExtensions
    {
        public static string WarningsConfirmation(this HtmlHelper htmlHelper)
        {
            if (htmlHelper.ViewData.ModelState.HasWarnings())
            {
                StringBuilder sb = new StringBuilder();
 
                sb.Append("
<fieldset>");
                sb.Append("
<legend>Ostrzeżenia</legend>
 
");
                sb.Append(htmlHelper.CheckBox("SuppressWarnings").ToString());
                sb.Append("<label for="/&quot;SupressWarnings/&quot;">Pomiń ostrzeżenia</label>");
                sb.Append("<span>Uwaga, formularz zawiera ostrzeżenia, przejrzyj je. Żeby potem zapisać go mimo wszystko zaznacz opcję 'Pomiń ostrzeżenia' i kliknij 'Zapisz'</span>");
                sb.Append("</fieldset>
");
                return sb.ToString();
            }
            else
                return "";
        }
 
        public static void AddModelWarning(this ModelStateDictionary ms, string key, string errorMessage)
        {
            ms.AddModelError(key, "Uwaga: " + errorMessage);
        }
 
        public static bool HasWarnings(this ModelStateDictionary ms)
        {
            foreach(ModelState s in ms.Values)
                if (s.Errors.Count &gt; 0)
                    foreach (ModelError e in s.Errors)
                        if (e.ErrorMessage.StartsWith("Uwaga: "))
                            return true;
 
            return false;
        }
    }

Aby skorzystać z tego należy stworzyć mniej więcej taki kod:

        public ActionResult Create(string ReturnUrl, Obiekt obj)
        {
                bool SuppressWarnings = !string.IsNullOrEmpty(collection["SuppressWarnings"]) &amp;&amp; (Convert.ToString(collection["SuppressWarnings"]).StartsWith("true"));
                if (!SuppressWarnings)
                {
                    if (dao.CzySaDuplikatyNIP(obj.NIP))
                        ModelState.AddModelWarning("Firma.NIP", "Firma o podanym numerze NIP już istnieje");
                }
 
                if (ModelState.IsValid)
                {
                    dao.Save(obj);
                    return RedirectToAction("Details", new { Id = Id });
                }

Kod jest uproszczony ale powinien oddawać mój zamysł. Jak to działa?

  • sprawdzamy czy użytkownik zaznaczył checkbox „Pomiń ostrzeżenia”
  • jeśli go nie zaznaczył – sprawdzamy poprawność danych pod tym kątem i dodajemy do stanu modelu odpowiednie ostrzeżenia metodą ModelState.AddModelWarning
  • jeśli w modeli nie ma błędów ani ostrzeżeń – zapisujemy zmiany
  • jeśli w modelu są błędy lub ostrzeżenia – wyświetlamy je standardowym helperem Html.ValidationMessage, w przypadku ostrzeżeń wyświetlamy dodatkowo kontrolkę „Pomiń ostrzeżenia”, którą użytkownik może potwierdzić że zapoznał się z tymi ostrzeżeniami i mimo wszystko chce zapisać dany formularz

Widok musimy zmodyfikować dodając wywołanie helpera Html.WarningsConfirmation()

    &lt;% using (Html.BeginForm()) {%&gt;
        &lt;%= Html.ValidationSummary() %&gt;
        &lt;%= Html.WarningsConfirmation() %&gt;
<fieldset>
<legend></legend>
 
        ... kontrolki edycyjne ...</fieldset>

Czego w tym rozwiązaniu mi brakuje:

  • Podłączenia się do DataAnnotations i deklaratywnego sprawdzania poprawności danych pod kątem ostrzeżeń,
  • Brak wizualnego rozgraniczenia ostrzeżeń i błędów w wyniku działania Html.ValidationMessage
  • Powtarzanie w metodach kontrolera kodu sprawdzającego stan kontrolki zatwierdzającej zapoznanie się z ostrzeżeniami.

Ale wraz z rozwojem aplikacji i to rozwiązanie będę udoskonalał. Proszę o wszelkie uwagi na temat tego rozwiązania oraz pierwszego prawdziwego posta na tym blogu.

DataAnnotations

Krótko o mnie

Posted in Bez kategorii on Wrzesień 25th, 2010 by admin – Be the first to comment

Kim jestem? W jednym zdaniu – jestem urodzonym programistą z 10-letnim stażem zawodowym. Do tego architektem, projektantem, ekspertem, fascynatem, menadżerem, testerem, wdrożeniowcem. Długo by opowiadać o wszystkich odcieniach bycia „programistą”.

Po co kolejny blog? Jak każdy, kto chce się rozwijać stawiam sobie kolejne wyzwania i próbuję je realizować trafiając po drodze na rozmaite problemy i rozwiązując je. To ostatnie byłoby niemożliwe gdyby nie Internet, Google i właśnie blogi, blogi ludzi którzy robili coś podobnego i postanowili podzielić się swoimi doświadczeniami. I dlatego postanowiłem dorzucić swoją cegiełkę do tej olbrzymiej bazy wiedzy, jako podziękowanie dla ludzi którzy wsparli mnie swoją wiedzą nie zdając sobie z tego nawet sprawy.

Co tu będzie? Głównie tematy związane z szeroko pojętym .NETem. Tyle ile czas pozwoli, bo tematów, które chciałbym poruszyć jest mnóstwo…