DI w bibliotece .dll

1

No właśnie o to mi chodzi, że ParamsLogger robi zbyt wiele. https://en.wikipedia.org/wiki/Single_responsibility_principle

0
somekind napisał(a):

No właśnie o to mi chodzi, że ParamsLogger robi zbyt wiele. https://en.wikipedia.org/wiki/Single_responsibility_principle

Ok, już rozumiem. Wydawało mi się, że jeśli klasa robi to jedynie przez interfejsy serwisów, to tak naprawdę one biorą na siebie ciężar pracy. Ale wnioskuję, że tak naprawdę one powinny wykonać całą pracę? Z zapisem nie ma problemu. Ale zastanawiam się jak skonfigurować obiekt loggera jeśli nie będzie on przyjmował konfiguracji...?

0
bakunet napisał(a):

Ok, już rozumiem. Wydawało mi się, że jeśli klasa robi to jedynie przez interfejsy serwisów, to tak naprawdę one biorą na siebie ciężar pracy.

No jest to możliwe, ale raczej nie w Twoim przypadku. Ale może się mylę, więc wyjaśnij - czemu masz Timer w tym ParamsLogger?

Ale zastanawiam się jak skonfigurować obiekt loggera jeśli nie będzie on przyjmował konfiguracji...?

No w tym rzecz, że powinien przyjmować konfigurację. A obecnie nie przyjmuje - konstruktor jest przeciez bezparametrowy.

0
somekind napisał(a):

(...)
No w tym rzecz, że powinien przyjmować konfigurację. A obecnie nie przyjmuje - konstruktor jest przeciez bezparametrowy.

Próbuję zrozumieć co dokładnie masz na myśli. Choć wydaje mi się, że powoli zaczynam kumać. Wcześniej ponownie wpadłem w swoją pułapkę, i idąc na łatwiznę skorzystałem z IoC rejestrując mój logger jako singleton. Teraz w każdej klasie próbuję utworzyć instancję na zasadzie:

private static readonly IParamsLogger _log = new ParamsLogger();

I tu zaczynają się schody. Wydaje mi się, że albo ponownie będę musiał gdzieś utworzyć singleton, albo utworzyć kolekcję loggerów, gdzie każdy kolejny będzie dodawany. Jeszcze nie wiem jak to ogarnąć, ale coś wymyślę. Inaczej skończę z n ilością instancji.

Jak chodzi o konfigurację samego loggera, to wydaje mi się, że będzie mógł być tworzony przy wykorzystaniu info ze stosu, więc nie muszę przyjmować nic w konstruktorze. Jak wspominałem wcześniej, pozostaje mi jedynie kwestia utworzenia jednego obiektu zamiast tuzina takich samych. A singleton lub kolekcja będą zasysać info z pliku konfiguracyjnego.

O to Ci chodziło, jestem blisko?

0
somekind napisał(a):

No właśnie o to mi chodzi, że ParamsLogger robi zbyt wiele. https://en.wikipedia.org/wiki/Single_responsibility_principle

W dzisiejszym odcinku Ulicy Sezamkowej się nauczyłem jak utworzyć singleton oraz wzorca fabryki. W fabryce ładuję konfigurację i przekazuję ją do właściwej klasy loggera. Nie wiem czy nie przekombinowałem trochę z tą własnością. Ale działa, lockuje się na wypadek kilku wątków, więc powinno być spoko. Też później będę chciał jeszcze spojrzeć świeżym okiem na połączenie fabryki + fasady.

Będę wdzięczny za wszelkie uwagi.

0
bakunet napisał(a):

I tu zaczynają się schody. Wydaje mi się, że albo ponownie będę musiał gdzieś utworzyć singleton, albo utworzyć kolekcję loggerów, gdzie każdy kolejny będzie dodawany. Jeszcze nie wiem jak to ogarnąć, ale coś wymyślę. Inaczej skończę z n ilością instancji.

Ale co w tym złego? Czemu Ci zależy na singletonie?

Jak chodzi o konfigurację samego loggera, to wydaje mi się, że będzie mógł być tworzony przy wykorzystaniu info ze stosu, więc nie muszę przyjmować nic w konstruktorze. Jak wspominałem wcześniej, pozostaje mi jedynie kwestia utworzenia jednego obiektu zamiast tuzina takich samych. A singleton lub kolekcja będą zasysać info z pliku konfiguracyjnego.

Jeśli masz obiekt z normalnym konsturktorem, w którym wstrzykujesz zależności, np. ParamsLogger(IFileService, IStringService), to w testach możesz utworzyć mocki, a w normalnym kodzie możesz mieć jakąś fabryczkę, która wczytuje konfiguracje z pliku, tworzy odpowiednie FileService oraz StringService, a na końcu faktyczny ParamsLogger.
Wszystko jest proste, eleganckie, testowalne, rozszerzalne i nie ma niespodzianek typu logger, który po utworzeniu wczytuje sobie sam swoją konfigurację z jakiegoś pliku.

0

@somekind:

Chcę mieć singleton, żeby mieć kontrolę nad zapisem logów do jednego pliku.

Co do fabryki to wydaje mi się że faktycznie może ona istnieć bez fasady. Popróbuję zaraz na prostych przykładach żeby ją lepiej zrozumieć i umieć wykorzystać w tym projekcie.

0

@somekind:

Poniżej mam uproszczony kod. Na razie udało mi się zrobić coś na zasadzie jak niżej. Chcę uniknąć wstrzykiwania zależności w konstruktor ObjectService, w przeciwnym wypadku IoC kontener aplikacji będzie chciał rozwiązać zależności. A nie chcę żeby projekt aplikacji wiedział o zależnościach biblioteki. Zastanawiam się jak rozwiązać problem podmieniania fabryki przy testowaniu. Więc stworzyłem własność Factory, która w teście jest podmieniana makietą:

public class ObjectService : IObjectService
        {
            public ObjectService()
            {
                Factory = new ObjectFactory();
            }

            public IObjectFactory Factory { get; set; }

            public IObjectModel GetObject(string firstName)
            {
                return Factory.GetObject(firstName);
            }
        }

Więc w teście jednostkowym wykorzystuję _factoryMock

public class ObjectServiceTests
        {
            private readonly ObjectService _serv;
            private readonly Mock<IObjectFactory> _factoryMock;
            private readonly Mock<ISomeService> _someServMock;
            private readonly string _someFirstName = "SomeFirstName";

            public ObjectServiceTests()
            {
                _someServMock = new Mock<ISomeService>();
                _someServMock.SetupGet(s => s.SecondName).Returns("Cos");

                _factoryMock = new Mock<IObjectFactory>();
                _factoryMock.Setup(f => f.GetObject(_someFirstName))
                    .Returns(new ObjectModel(_someFirstName, _someServMock.Object));

                _serv = new ObjectService();
            }

            [Fact]
            public void GetObject_Called_ReturnsObject()
            {
                _serv.Factory = _factoryMock.Object;

                IObjectModel newObj = _serv.GetObject(_someFirstName);

                Assert.Equal(_someFirstName + ", Cos", newObj.FullName);
            }
        }

Zastanawiam się czy wykorzystanie public IObjectFactory Factory { get; set; } jest poprawne? Na razie nie mam lepszego pomysłu.

EDIT właśnie wyczytałem, że to jest forma property DI. Chyba przy niej zostanę, jako że zaspokaja moje oczekiwania.

0

Ok, chyba dopiąłem temat:

Choć w fabryce mogłem interfejsy z tej metody wczytywać do Loggera inaczej, ale to już zostawiam na przyszłość TODO

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