Uniemożliwienie tworzenia obiektów klasy z jednym wyjątkiem

Odpowiedz Nowy wątek
2014-12-22 01:35
Zimny Krawiec
0

Czy jest jakaś możliwość w C#, uniemożliwienie tworzenia obiektów klasy, z wyjątkiem jednej, innej klasy. W C++ mógłbym dać prywatny konstruktor i firendi to załatwiło by sprawę.

A co chce osiągnąć: chce mieć taki jakby singleton, który jest dostępny jedynie z poziomu innej niestatycznej klasy. Innymi słowy: mam system logowania, który umożliwia jednocześnie zalogowanie tylko jednego użytkownika, za system logowania i zarządzania kontami odpowiada klasa: AccountManagement, chce aby miała ona właściwość CurrentUser, która zwraca ten mój singleton, ale chce również aby obiekt tej klasy nie mógł być tworzony nigdzie indziej oprócz klasy AccountManagement.

Pozostało 580 znaków

2014-12-22 01:41
0

Zwykły singleton + internal class?

Pozostało 580 znaków

2014-12-22 01:52
Zimny Krawiec
0

Nie mogę dać internal class, klasa AccountManagement, jest umieszczona w DLL i jest wykorzystywana w innych projektach, także internal class, powodowała by błąd poziomu dostępności.

Pozostało 580 znaków

2014-12-22 03:13
1

Zawsze można użyć refleksji do sprawdzenia jaka klasa wywołuje daną metodę.
Tylko jaki jest cel tego wszystkiego? Chcesz się zabezpieczyć przed swoim błędem?


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2014-12-22 10:24
Krwawy Krawiec
0

Zawsze byłem uczony żeby uniemożliwiać wykonanie wszystkiego co nie powinno być wykonane, tak jak w tym przypadku z oczywistych przyczyń nie chce aby dostęp do danych zalogowanego użytkownika były w globalnym zasięgu. Tak jest to pewien sposób zabezpieczenia, dziś z kodu korzystam tylko ja, ale nigdy nie wiadomo czy za rok tak będzie.

Jak dla mnie perełka, kod broniący się przed programistą - spartanPAGE 2014-12-22 10:37
@spartanPAGE nie rozumiem perełki... Po coś są przecież sealed np. Wg mnie to akurat dobra technika uszczelniania kodu. - misiakufal 2014-12-22 11:03

Pozostało 580 znaków

2014-12-22 11:04
Krwawy Krawiec
0

@spartanPAGE nie rozumiem Twojego toku rozumowania, co jest złego w tym aby zadbać o to aby coś co nie powinno być dostępne globalnie takie nie było?

Wracając do tematu, rozwiązanie nie okazało się skomplikowane, stworzyłem publiczną stealed klase CurrentUser z konstruktorem o dostępności internal, przez co nie mogę tworzyć tego obiektu w innych odwołaniach, ale mogę się do niego dobrać jedynie przez właściwość CurrentUserklasy AccountManagement - to tak dla potomnych.

Pozostało 580 znaków

2014-12-22 12:42
1
Krwawy Krawiec napisał(a):

@spartanPAGE nie rozumiem Twojego toku rozumowania, co jest złego w tym aby zadbać o to aby coś co nie powinno być dostępne globalnie takie nie było?

Nic, poza tym, że chyba nie bardzo rozumiesz ideę zabezpieczania. Bo w sumie, to ani to nie zwiększa bezpieczeństwa aplikacji, ani nie sprawia, że programista popełni mniej błędów. Więc o co chodzi w tym "zabezpieczeniu"?

Wracając do tematu, rozwiązanie nie okazało się skomplikowane, stworzyłem publiczną stealed klase CurrentUser z konstruktorem o dostępności internal, przez co nie mogę tworzyć tego obiektu w innych odwołaniach, ale mogę się do niego dobrać jedynie przez właściwość CurrentUserklasy AccountManagement - to tak dla potomnych.

1) sealed nie ma wpływu na widoczność klasy.
2) Możesz utworzyć ten obiekt w każdej klasie z tego assembly, tak działa internal.
3) A w każdej innej klasie na świecie możesz zrobić po prostu:

var currentUser = typeof(CurrentUser).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance).Single().Invoke(null) as CurrentUser;

Tyle z tego zabezpieczenia.


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2014-12-22 13:27
msm
1

Jak dla mnie perełka, kod broniący się przed programistą - spartanPAGE dzisiaj, 10:37

Tak samo jak modyfikator private - niby jeśli ktoś się uprze/potrzebuje, można go obejść (w C++ również), ale to bardziej informacja dla programisty "nie dotykaj, szczegół implementacyjny".

Czy jest jakaś możliwość w C#, uniemożliwienie tworzenia obiektów klasy, z wyjątkiem jednej, innej klasy. W C++ mógłbym dać prywatny konstruktor i firend i to załatwiło by sprawę.

1) Ogólnie moim zdaniem może myślisz w dobrym kierunku, ale idziesz w złą stronę. Jeśli klasa jest publiczna - mogą ją stworzyć wszyscy. Friend i inne wynalazki tylko tworzą kolejny poziom skomplikowania i niejawne powiązania między klasami, które komplikują sytuację - nie bez powodu ich w końcu w C# nie ma.
2) Jeśli martwi Cię kto ma tworzyć ten obiekt - zastanów się na przykład czy jakieś dependency injection by Ci nie ułatwiło sytuacji.
3) I ogólnie, nie ma co przesadzać i zakładać że każdy programista piszący kod w Twoim projekcie nic nie robi poza myśleniem jak wprowadzić błędy.

Jeśli chodzi o temat, coś co faktycznie uniemożliwia tworzenie obiektu (pierwsza myśl przynajmniej):

class SecureClass
{
    public SecureClass()
    {
        StackTrace trace = new StackTrace();
        StackFrame frame = trace.GetFrame(1); // z jakiej metody został wywołany ten konstruktor
        if (frame.GetMethod().DeclaringType != typeof(Ok)) // jeśli metoda jest w złej klasie
        { 
            throw new InvalidOperationException("Nope"); // rzucamy błąd
        }
    }
}

Ale nie używaj tego, naprawdę (bo to faktycznie kod wrogi programiście, i lista problemów z tym by była tak długa że nawet nie zaczynam pisać).

edytowany 4x, ostatnio: msm, 2014-12-22 13:30
To wspaniałe, że zaimplementowałeś to, o czym pisałem w 1 poście. :P - somekind 2014-12-22 13:35

Pozostało 580 znaków

2014-12-22 16:38
0

Jest jeszcze taka opcja, żeby stworzyć interfejs np. IUser i ustalić go jako typ dla CurrentUser. A klasę, która go implementuje ukryć jako prywatną w AccountManagement.
Ogólnie to co chcesz zrobić brzmi dziwnie. Nie wystarczy prywatny setter dla CurrentUser, żeby nie można ustawić tego pola poza klasą? Wtedy AccountManagement będzie mieć pełną kontrolę nad tworzeniem tego obiektu i czasem kiedy to ma się stać.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0