Skip to content

Instantly share code, notes, and snippets.

@IanWold
Created May 4, 2024 13:26
Show Gist options
  • Save IanWold/7efdf5df24bdd4e6ff5c652e1c051d6f to your computer and use it in GitHub Desktop.
Save IanWold/7efdf5df24bdd4e6ff5c652e1c051d6f to your computer and use it in GitHub Desktop.
public class DatabaseQueryResult<T>
{
private enum ResultType
{
Found,
Empty,
ClientError,
ServerError
}
private DatabaseQueryResult() { }
private ResultType Type { get; set; }
private T? Value { get; set; }
private string? ErrorDescription { get; set; }
public bool IsFound([NotNullWhen(true)] out T? value)
{
value = Value;
return Type == DatabaseQueryResultType.Found;
}
public bool IsError([NotNullWhen(true)] out string? description)
{
description = ErrorDescription;
return
Type == DatabaseQueryResultType.ClientError
|| Type == DatabaseQueryResultType.ServerError;
}
public static DatabaseQueryResult<T> Found(T Value) => new()
{
Type = DatabaseQueryResultType.Found
Value = value
};
public static DatabaseQueryResult<T> Empty() => new()
{
Type = DatabaseQueryResultType.Empty
};
public static DatabaseQueryResult<T> ClientError(string description) => new()
{
Type = DatabaseQueryResultType.ClientError,
ErrorDescription = description
};
public static DatabaseQueryResult<T> ServerError(string description) => new()
{
Type = DatabaseQueryResultType.ServerError,
ErrorDescription = description
};
}
public DatabaseQueryResult<IEnumerable<Item>> GetAllItemsFromDatabase(...)
{
try
{
var result = ContactDatabaseSomehow(...);
if (result is IEnumerable<Item> items)
{
return DatabaseQueryResult<IEnumerable<Item>>.Found(items);
}
}
catch (/*exception indicating client error*/)
{
return DatabaseQueryResult<IEnumerable<Item>>.ClientError(exception.Message);
}
catch (/*exception indicating server error*/)
{
return DatabaseQueryResult<IEnumerable<Item>>.ServerError(exception.Message);
}
return DatabaseQueryResult<IEnumerable<Item>>.Empty();
}
public void ShowItems()
{
var result = GetAllItemsFromDatabase(...);
if (result.IsFound(out var items))
{
foreach (var item in items)
{
Console.WriteLine(item.ToString());
}
}
else if (result.IsError(out var description))
{
Console.WriteLine($"Error! {description}");
}
else
{
Console.WriteLine("No items found!");
}
}
public record Found<T>(T Value);
public record Empty();
public record ClientError(string Description);
public record ServerError(string Description);
public sealed class DatabaseQueryResult<T>
{
private object _value;
private DatabaseQueryResult<T>(object value) =>
_value = value;
public bool IsSuccess([NotNullWhen(true)] out T? value)
{
if (_value is Found<T> found)
{
value = found.Value;
return true;
}
_value = default;
return false;
}
public bool IsError([NotNullWhen(true)] out string? description)
{
description = null;
if (_value is ClientError clientError)
{
description = clientError.Description;
}
if (_value is ServerError serverError)
{
description = serverError.Description;
}
return description is null;
}
public bool IsEmpty() =>
_value is Empty;
public U Map<U>(
Func<T, U> found,
Func<U> empty,
Func<string, U> error
)
{
if (_value is Found<T> foundValue)
{
return found(foundValue.Value);
}
else if (_value is ClientError clientErrorValue)
{
return error(clientErrorValue.Description);
}
else if (_value is ServerError serverErrorValue)
{
return error(serverErrorValue.Description);
}
return empty();
}
public U Map<U>(
Func<T, U> found,
Func<U> empty,
Func<string, U> clientError,
Func<string, U> serverError
)
{
if (_value is Found<T> foundValue)
{
return found(foundValue.Value);
}
else if (_value is ClientError clientErrorValue)
{
return clientError(clientErrorValue.Description);
}
else if (_value is ServerError serverErrorValue)
{
return serverError(serverErrorValue.Description);
}
return empty();
}
public void Match(
Action<T> found,
Action empty,
Action<string> error
)
{
if (_value is Found<T> foundValue)
{
found(foundValue.Value);
}
else if (_value is ClientError clientErrorValue)
{
error(clientErrorValue.Description);
}
else if (_value is ServerError serverErrorValue)
{
error(serverErrorValue.Description);
}
empty();
}
public Match(
Action<T> found,
Action empty,
Action<string> clientError,
Action<string> serverError
)
{
if (_value is Found<T> foundValue)
{
found(foundValue.Value);
}
else if (_value is ClientError clientErrorValue)
{
clientError(clientErrorValue.Description);
}
else if (_value is ServerError serverErrorValue)
{
serverError(serverErrorValue.Description);
}
empty();
}
public static implicit operator DatabaseQueryResult<T>(Found<T> found) => new();
public static implicit operator DatabaseQueryResult<T>(Empty empty) => new();
public static implicit operator DatabaseQueryResult<T>(ClientError clientError) => new();
public static implicit operator DatabaseQueryResult<T>(ServerError serverError) => new();
}
public DatabaseQueryResult<IEnumerable<Item>> GetAllItemsFromDatabase(...)
{
try
{
var result = ContactDatabaseSomehow(...);
if (result is IEnumerable<Item> items)
{
return new Found<IEnumerable<Item>>(items);
}
}
catch (/*exception indicating client error*/)
{
return new ClientError(exception.Message);
}
catch (/*exception indicating server error*/)
{
return new ServerError(exception.Message);
}
return new Empty();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment