184 lines
4.9 KiB
Markdown
184 lines
4.9 KiB
Markdown
|
# 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, Nickname = "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.Nickname = "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.Nickname = "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";
|
|||
|
}
|
|||
|
```
|