2010-07-08 13 views
8

W kodzie w pracy, mamy wiele zastosowań magicznych ciągów jak poniższym fragmencie kodu:.net - Strategie uniknąć magiczne ciąg

if (user.HasRight("Profile.View")) {...} 

więc istnieje wiele miejsc, gdzie mijamy ciąg jako parametr zobacz, czy użytkownik ma określone prawo. Nie podoba mi się to, ponieważ generuje wiele magicznych ciągów.

Jaki byłby lepszy sposób na zrobienie tego?

Enum, stała, klasa?

Odpowiedz

17

W tym konkretnym przypadku użyj Enum. Nie będzie żadnych magicznych strun i jeśli Enum się zmieni (w sposób, który przełamie magiczne rozwiązanie), aplikacja nie będzie się już kompilować.

public enum ProfilePermissions 
{ 
    View, 
    Create, 
    Edit, 
    Delete 
} 

Następnie można po prostu:

if(user.HasRight(ProfilePermissions.View)) { } 

Można również użyć klasy, ale wtedy ograniczyć się jeśli chodzi o bardziej skomplikowane scenariusze. Na przykład, prosta zmiana wyliczania do czegoś podobnego:

public enum ProfilePermissions 
{ 
    View = 1, 
    Create = 2, 
    Edit = 4, 
    Delete = 8 
} 

pozwoliłoby na korzystanie operatory bitowe dla bardziej skomplikowanych uprawnień (na przykład sytuacji, w której potrzebuje użytkownik albo utworzyć lub usunąć):

if(user.HasRight(ProfilePermissions.Create | ProfilePermissions.Delete)); 
+1

W zależności od potrzeb może to być również przekształcony w flagi-wyliczenia, czyli gdzie wartości mogą być łączone za pomocą '|', na przykład za pomocą 0x1 wartości , 0x2, 0x4, etc ... –

+1

Dobra odpowiedź i moja odpowiedź była identyczna. Mogę dodać, że celem 'enum' jest stworzenie" listy wyliczeniowej "stałych. Grupowanie stałych, w których mogą być wymienione w ten sposób, jest świetnym pomysłem i zapewnia programowi również bardziej logiczny przebieg. – Armstrongest

+0

W przypadku, gdy wymagana jest również reprezentacja ciągów znaków, np. Aby przechowywać zestaw uprawnień w czytelny dla człowieka sposób, możesz po prostu wywołać 'ProfilePermissions.View.ToString()', aby uzyskać ciąg "Widok", lub jeśli potrzebujesz niestandardowej reprezentacji ciągów, możesz dodać dekorowanie * Opis * atrybut opisany tutaj: http://blogs.msdn.com/b/abhinaba/archive/2005/10/20/483000.aspx –

0

Możesz wykonywać ciągłe ciągi w C#.

Można zdefiniować wszystkie struny w nagłówku tak:

const string PROFILE_VIEW "Profile.View"; 

Nie wiem, czy to jest „najlepszy” sposób, ale jest na pewno lepsze niż wartości magiczne w kodzie.

5

Jest to również dość powszechne w środowisku .NET. Przykładami są System.Windows.DataFormats i System.Net.WebRequestMethods.Http. że chcesz różnorodność readonly:

public static class MumbleRights { 
    public static readonly string ProfileView = "Profile.View"; 
    // etc.. 
} 
+4

Dlaczego tylko czytać, a nie const? – sunside

+5

@ Markus, jeśli publiczne stałe są używane ze zgromadzenia zewnętrznego, są one pieczone; jeśli później zmienisz swoją publiczną stałą, zewnętrzny zespół nadal będzie używał stałej, którą zobaczył podczas kompilacji. –

+1

http://stackoverflow.com/questions/277010/what-are-the-benefits-to-marking-a-field-as-readonly-in-c/312840#312840 –

1

Tworzenie klasy, która silnie typy tych właściwości, jak

public static class UserInfo 
{ 
    public static bool CanViewProfile { get { return User.HasRight("Profile.View"); } } 
} 

Pozwoli to zachować swoje „magiczne ciągi” w jednym miejscu w kodzie. Enum też zadziała, ale moim zdaniem nie jest tak czytelny.

Uwaga: mój przykład ma działać jako proxy właściwości dla zalogowanego użytkownika, czyli klasy statycznej. Jeśli chciałbyś czegoś, co działałoby na bardziej bezpośrednie dane (np. Listę użytkowników), ten typ klasy musiałby być niestatyczny i utworzony na podstawie konta użytkownika.

+0

'CanViewProfile' nie ma w moim odczuciu właściwości statycznej i powinno być raczej metodą instancji obiektu użytkownika. Fragment sugeruje, że dla każdego użytkownika byłaby klasa statyczna? –

+0

Nie, nie sugeruję klasy statycznej dla każdego użytkownika. Powyższa klasa działa jedynie jako proxy dla właściwości zalogowanego użytkownika. (Użyłem "Alice", ponieważ jestem przyzwyczajony do używania alice, bob, charlie, david, etc zamiast foo/bar. –

0

Ja po drugie sposób pokazany przez "Justin Niessner". Ale w niektórych przypadkach wolałbym pisać po konstrukcji kodu.

public class User 
    { 
     public Permission Permission { get; set; } 

    } 
    public abstract class Permission 
    { 

    } 
    public class ViewPermission:Permission 
    { 

    } 

i można spożywać go jako

User user=new User(); 
      if(user.Permission is ViewPermission) 
      { 

      } 
3

metod przedłużających! Trzymaj je w tym samym miejscu, aby śledzić wszystkie magiczne ciągi.

public static class UserRightsExtensions { 
    public static bool CanReadProfile(this User user) 
    { 
    return user.HasRight("Profile.View"); 
    } 

    // etc.. 
} 

Następnie można:

if (user.CanReadProfile()) .....