session-companion/SessionCompanion/SessionCompanion.Extensions/EitherType/EitherDocumentation.md

184 lines
4.9 KiB
Markdown
Raw Permalink Normal View History

# Either
### Jak u<>ywa<77>
Either umo<6D>liwa nam zwr<77>cenie z metody b<>d<EFBFBD> nawet kontrolera, dw<64>ch mo<6D>liwych wynik<69>w.
Dla u<>atwienia zrozumienai poni<6E>ej podaj<61> przyk<79>ady stosowania.
Jako typ zmiennej zwracanej z api:
W tym przypadku wskazujemy, <20>e nasze api zwr<77>ci albo CharacterViewModel albo ErrorResponse
```cs
public async Task<Either<CharacterViewModel, ErrorResponse>> Get(int id)
```
Aby zwr<77>ci<63> ten typ mamy dwie mo<6D>liwo<77>ci.
Mo<EFBFBD>emy wywo<77>a<EFBFBD> metod<6F> z serisu, kt<6B>ra ma nam zwr<77>ci<63> CharacterViewModel.
Nast<EFBFBD>pnie sprawdzi<7A> czy otrzymana warto<74><6F> CharacerViewModel zawiera jakiekolwiek dane i odpowiednio, je<6A>li tak to zwracamy otrzymany viewmodel a je<6A>li nie tworzymy ErrorResponse i zwracamy wynik:
```cs
public async Task<Either<CharacterViewModel, ErrorResponse>> Get(int id)
{
Either<CharacterViewModel, ErrorResponse> result = await _service.Get(id);
if (result.Left != null)
{
return result;
}
else
{
result = new ErrorResponse { StatusCode = 400, Message = "Co<43> posz<73>o nie tak" };
return result;
}
}
```
W przypadku jesli serwis nie znajdzie warto<74>ci otrzymamy:
```json
{
"left":null,
"right":{
"statusCode":400,
"message":"Co<43> posz<73>o nie tak"},
"isLeft":false}
```
Drugim sposobem jest zmiana dzia<69>ania serwisu:
```cs
public async Task<Either<CharacterViewModel, ErrorResponse>> GetCharacter(int id)
{
var repoResult = await this.Repository.Get(id);
if (repoResult != null)
{
return Mapper.Map<CharacterViewModel>(repoResult);
}
else
{
return new ErrorResponse()
{
StatusCode = 404,
Message = "Co<43> posz<73>o nie tak"
};
}
}
```
Wtedy kontroler wygl<67>da tak :
```sh
public async Task<Either<CharacterViewModel, ErrorResponse>> Get(int id)
{
return await this._service.GetCharacter(id);
}
```
### Przypisanie nowej warto<74>ci
Je<EFBFBD>li z jakiego<67>powodu b<>dziemy chcieli zmieni<6E> warto<74><6F> obiektu Either, musimy dokona<6E> tego w taki oto spos<6F>b:
```cs
UserViewModel user = new UserViewModel() { Id = 1, Username = "Testowy", Password = "Secret" };
Either<UserViewModel, string> test = "asd";
// zmieniamy warto<74><6F> Either
test = user;
// Warto zauwa<77>y<EFBFBD>, <20>e mo<6D>emy zmieni<6E> warto<74><6F> obiektu znajdujacego si<73> wewn<77>trz
// kt<6B>rej<65> ze zmiennej o ile jest on publiczny
test.Left.Username = "test";
// Jednak je<6A>li dokonamy tego po zmianie warto<74>ci obietu na inny pomimo tego, <20>e
// dla kodu jest to ok, to nie zadzia<69>a to poprawnie, poniewa<77> warto<74><6F> starego obiektu
// jest zmieniana na null(dla boola na false)
test = "asd";
test.Left.Username = "b<><62>d";
```
### LeftOrDefault() oraz RightOrDefault()
Zwracaj<EFBFBD> one warto<74><6F> wybranej zmiennej b<>d<EFBFBD> jej warto<74><6F> defaultow<6F>.
Dla wiekszo<7A>ci obiekt<6B>w jest to null, wyjatkiem jest tutaj bool, kt<6B>ry zwr<77>ci nam false.
```cs
var test = (Either<bool, string>)true;
var a = test.LeftOrDefault(); // zwr<77>ci nam true
var b = test.RightOrDefault(); // zwr<77>ci nam null
test = "asd";
var c = test.LeftOrDefault(); // zwr<77>ci nam false
var d = test.RightOrDefault(); // zwr<77>ci nam "asd"
```
### Match
Funkcja ta pozwala nam na odpalenie odpowiedniej metody w zale<6C>no<6E>ci od tego jako typ zmiennej jest aktualnie przechowywany w obiekcie Either. Niestety ograniczeniem jest to, ze obie funkcje musza docelowo zwr<77>ci<63> ten sam typ.
```cs
// <20>adujemy userviewmodel do obiektu Either i wywo<77>ywamy matcha pdaj<61>c dwie funkcje
test = user;
// zwwr<77>cny zostanie string "Test1"
test.Match(this.Test1, this.Test2);
// <20>adujemy stringa do obiektu Either i wywo<77>ywamy matcha pdaj<61>c dwie funkcje
test = "asd";
// zwwr<77>cny zostanie string "Test2"
test.Match(this.Test1, this.Test2);
public string Test1(UserViewModel viewModel)
{
return "Test1";
}
public string Test2(string text)
{
return "Test2";
}
```
Warto zauwa<77>y<EFBFBD>, <20>e mo<6D>emy wykorzysta<74> tutaj lambde by rozszerzy<7A> nasze mo<6D>liwo<77>ci:
```cs
test = "asd";
test.Match(
Test1,
second =>
{
int z = Test2(second);
// tutaj mo<6D>emy robi<62> ju<6A> co nam si<73> tylko podoba
// pami<6D>ta<74> nale<6C>y ze finalnie musimy co<63> zwr<77>ci<63>
// chyba, <20>e nasze obie funkcje s<> typu void
return z.ToString();
});
public string Test1(UserViewModel viewModel)
{
return "Test1";
}
public int Test2(string text)
{
return 12;
}
```
Mo<EFBFBD>emy te<74> poda<64> jedna funkcj<63> typu void a drug<75> typu innego np. string albo int:
```cs
y = "";
test = "asd";
test.Match(
Test1,
second =>
{
var x = this.Test2(second);
//jednak nie ma mo<6D>liwo<77>ci zwr<77>cenia warto<74>ci
// mo<6D>emy za to zwr<77>ci<63> wyniki do zewn<77>trznej zmiennej
y = x;
});
public void Test1(UserViewModel viewModel)
{
//...co<63> robi
}
public string Test2(string text)
{
return "Test2";
}
```