Olive
Overview
Olive is a productivity framework for .NET developed by Geeks Ltd. It provides a comprehensive set of extension methods and utility classes that reduce boilerplate in business application development. The framework covers string manipulation, collection operations, date/time helpers, validation utilities, file handling, and more.
Olive's philosophy is to make common operations fluent and null-safe through extension methods. Instead of writing defensive null checks and multi-line utility methods, Olive provides concise, chainable operations that handle edge cases like null or empty inputs gracefully.
Install via NuGet:
dotnet add package Olive
String Extensions
Olive provides null-safe string operations that eliminate defensive coding patterns.
using Olive;
// Null-safe operations
string? nullStr = null;
string result = nullStr.OrEmpty(); // ""
string trimmed = nullStr.TrimOrNull(); // null
string defaulted = nullStr.Or("default"); // "default"
// String validation
bool isEmail = "user@example.com".IsValidEmail(); // true
bool isUrl = "https://example.com".IsValidUrl(); // true
bool hasValue = "hello".HasValue(); // true
bool isEmpty = "".IsEmpty(); // true
// Transformations
string safe = "my file (1).txt".ToSafeFileName(); // sanitized for filesystem
string pascal = "hello world".ToPascalCase(); // "HelloWorld"
string camel = "hello world".ToCamelCase(); // "helloWorld"
// Truncation and wrapping
string truncated = "A very long string that needs truncating".Summarize(20);
string wrapped = "content".WithWrappers("<b>", "</b>"); // "<b>content</b>"
// Contains and comparison
bool contains = "Hello World".Contains("world", caseSensitive: false); // true
string removed = "Hello World".Remove("World"); // "Hello "
string replaced = "foo-bar-baz".RemoveFrom("-"); // "foo"
Collection Extensions
Fluent collection operations with null safety and LINQ enhancements.
using System;
using System.Collections.Generic;
using System.Linq;
using Olive;
var items = new List<string> { "apple", "banana", "cherry", "date" };
// Null-safe enumeration
List<string>? nullList = null;
var safe = nullList.OrEmpty(); // returns empty enumerable, not null
// Fluent operations
string joined = items.ToString(", "); // "apple, banana, cherry, date"
bool hasAny = items.HasAny(); // true
bool none = items.None(); // false
// Batch processing
var batches = items.ChunkBy(2); // [[apple, banana], [cherry, date]]
// Distinct by selector
var people = new[]
{
new { Name = "Alice", Dept = "IT" },
new { Name = "Bob", Dept = "IT" },
new { Name = "Carol", Dept = "HR" }
};
var distinctByDept = people.DistinctBy(p => p.Dept);
// Add/remove fluently
var extended = items.Concat("elderberry").ToList();
var without = items.Except("banana").ToList();
// Safe indexing
var firstOrNull = items.FirstOrDefault();
Date and Time Helpers
Simplified date arithmetic and formatting extensions.
using System;
using Olive;
var now = DateTime.Now;
// Relative dates
var tomorrow = now.AddDays(1);
var nextWeek = now.AddDays(7);
// Fluent date construction
var specificDate = 15.June(2025); // June 15, 2025
var christmas = 25.December(2025);
// Time rounding
var rounded = now.RoundToNearest(TimeSpan.FromMinutes(15));
// Date checks
bool isWeekend = now.IsWeekend();
bool isWeekday = now.IsWeekday();
bool isToday = specificDate.IsToday();
// Range operations
bool isBetween = now.IsBetween(
new DateTime(2025, 1, 1),
new DateTime(2025, 12, 31));
// Formatting
string relative = tomorrow.ToTimeDifferenceString(); // "tomorrow"
string friendly = now.ToFriendlyDateString();
Type Conversion Extensions
Safe type conversion utilities that handle parsing with fallbacks.
using Olive;
// Safe parsing with defaults
int number = "42".To<int>(); // 42
int fallback = "not-a-number".To<int>(); // 0 (default)
double price = "19.99".To<double>(); // 19.99
// Nullable parsing
int? nullable = "42".ToIntOrNull(); // 42
int? nullResult = "abc".ToIntOrNull(); // null
double? dbl = "3.14".ToDoubleOrNull(); // 3.14
// Boolean parsing
bool yes = "yes".ToBoolean(); // true
bool one = "1".ToBoolean(); // true
bool trueStr = "true".ToBoolean(); // true
// Enum parsing
var status = "Active".To<Status>();
public enum Status { Active, Inactive, Pending }
IO and File Utilities
File system operations with safety and convenience methods.
using System.IO;
using Olive;
// Safe file name generation
string safeName = "Report (Q1/2025).pdf".ToSafeFileName();
// Removes or replaces invalid characters
// File extension checking
bool isPdf = "document.pdf".HasExtension(".pdf"); // true
string noExt = "document.pdf".TrimEnd(".pdf");
// Directory operations
var tempDir = Path.GetTempPath();
var appDir = Path.Combine(tempDir, "MyApp");
// Ensure directory exists
Directory.CreateDirectory(appDir);
// Path combination (null-safe)
string fullPath = new[] { tempDir, "MyApp", "data", "file.json" }
.Where(p => p.HasValue())
.Aggregate(Path.Combine);
Building Services with Olive Extensions
Integrate Olive utilities into service classes for cleaner business logic.
using System;
using System.Collections.Generic;
using System.Linq;
using Olive;
public class CustomerService
{
public IReadOnlyList<Customer> Search(string? query, string? department)
{
var customers = GetAllCustomers();
return customers
.Where(c => query.IsEmpty() || c.Name.Contains(query, caseSensitive: false))
.Where(c => department.IsEmpty() || c.Department.OrEmpty() == department)
.OrderBy(c => c.Name)
.ToList();
}
public string FormatCustomerSummary(Customer customer)
{
var parts = new[]
{
customer.Name,
customer.Email.HasValue() ? $"({customer.Email})" : null,
customer.Department.Or("Unassigned")
};
return parts.Where(p => p.HasValue()).ToString(" ");
}
public ValidationResult Validate(CustomerInput input)
{
var errors = new List<string>();
if (input.Name.IsEmpty())
errors.Add("Name is required");
if (input.Email.HasValue() && !input.Email.IsValidEmail())
errors.Add("Invalid email format");
return new ValidationResult(errors.None(), errors);
}
private IEnumerable<Customer> GetAllCustomers() => Enumerable.Empty<Customer>();
}
public record Customer(string Name, string? Email, string? Department);
public record CustomerInput(string? Name, string? Email);
public record ValidationResult(bool IsValid, IReadOnlyList<string> Errors);
Olive vs Standard .NET
| Operation | Standard .NET | Olive |
|---|---|---|
| Null-safe string | str ?? string.Empty | str.OrEmpty() |
| Email validation | Regex or MailAddress parse | str.IsValidEmail() |
| Safe file name | Manual char replacement | str.ToSafeFileName() |
| Collection join | string.Join(", ", list) | list.ToString(", ") |
| Null-safe enumeration | list ?? Enumerable.Empty<T>() | list.OrEmpty() |
| Type conversion | int.TryParse(str, out var n) | str.To<int>() |
| Date check | date.DayOfWeek == ... | date.IsWeekend() |
Best Practices
- •Use
OrEmpty()andOr("default")at API boundaries to convert nullable strings into safe values immediately, eliminating null-check boilerplate in downstream code. - •Prefer
.HasValue()over!string.IsNullOrWhiteSpace()for readability and consistency with Olive's fluent style throughout your codebase. - •Use
.IsValidEmail()for quick input validation but supplement with actual email delivery verification for critical flows, since format validation alone is insufficient. - •Apply
.ToSafeFileName()on all user-provided file names before writing to disk to prevent path traversal and invalid character errors. - •Use
.To<T>()for configuration parsing where missing or invalid values should silently default, and.ToIntOrNull()when you need to detect and report invalid input. - •Avoid mixing Olive extensions with standard LINQ carelessly -- pick a consistent style within each service class so the code reads uniformly.
- •Use
.OrEmpty()on collection parameters at the start of methods to avoid null-reference exceptions when callers pass null collections. - •Prefer Olive's
.ToString(separator)on collections overstring.Join()for consistency with the fluent extension method style. - •Keep Olive usage in application/service layers rather than in domain entities, since domain types should be self-validating and not depend on utility extensions.
- •Pin the Olive NuGet version in your project to avoid breaking changes across minor versions, since the library evolves its API surface actively.