first commit

This commit is contained in:
2026-04-16 21:05:21 +04:30
commit 49591985ac
283 changed files with 12716 additions and 0 deletions
@@ -0,0 +1,27 @@
namespace Vizhvizh.BuildingBlocks.Domain.Contract;
public abstract record CommandBase<T> : ICommand<T>
{
public Guid Id { get; private set; }
protected CommandBase()
{
Id = Guid.NewGuid();
}
protected CommandBase(Guid id)
{
Id = id;
}
}
public abstract record CommandBase : ICommand
{
public Guid Id { get; private set; }
protected CommandBase()
{
Id = Guid.NewGuid();
}
protected CommandBase(Guid id)
{
Id = id;
}
}
@@ -0,0 +1,11 @@
namespace Vizhvizh.BuildingBlocks.Domain.Contract;
public interface ICommand<out TResult>
{
Guid Id { get; }
}
public interface ICommand
{
Guid Id { get; }
}
@@ -0,0 +1,5 @@
namespace Vizhvizh.BuildingBlocks.Domain.Contract;
public interface INotification
{
}
@@ -0,0 +1,5 @@
namespace Vizhvizh.BuildingBlocks.Domain.Contract;
public interface IQuery<out TResult>
{
}
@@ -0,0 +1,14 @@
namespace Vizhvizh.BuildingBlocks.Domain;
public class DomainEventBase : IDomainEvent
{
public Guid Id { get; }
public DateTime OccurredOn { get; }
public DomainEventBase()
{
this.Id = Guid.NewGuid();
this.OccurredOn = DateTime.UtcNow;
}
}
+37
View File
@@ -0,0 +1,37 @@
using Vizhvizh.BuildingBlocks.Domain.Exceptions;
namespace Vizhvizh.BuildingBlocks.Domain;
public abstract class Entity<T>
where T : ITypeIdValueBase
{
public Entity()
{
CreateOn = DateTime.Now;
}
public T Id { get; protected set; }
public DateTime CreateOn { get; init ; }
private List<IDomainEvent> _domainEvents;
public void ClearDomainEvents()
{
_domainEvents?.Clear();
}
protected void AddDomainEvent(IDomainEvent domainEvent)
{
_domainEvents ??= [];
this._domainEvents.Add(domainEvent);
}
public IReadOnlyList<IDomainEvent> DomainEvents => _domainEvents;
protected void CheckRule(IBusinessRule rule)
{
if (rule.IsBroken())
{
throw new BusinessRuleValidationException(rule);
}
}
}
@@ -0,0 +1,20 @@
namespace Vizhvizh.BuildingBlocks.Domain.Exceptions;
public class BusinessRuleValidationException : Exception
{
public IBusinessRule BrokenRule { get; }
public string Details { get; }
public BusinessRuleValidationException(IBusinessRule brokenRule)
: base(brokenRule.Message)
{
BrokenRule = brokenRule;
this.Details = brokenRule.Message;
}
public override string ToString()
{
return $"{BrokenRule.GetType().FullName}: {BrokenRule.Message}";
}
}
@@ -0,0 +1,8 @@
namespace Vizhvizh.BuildingBlocks.Domain.Exceptions;
public interface IBusinessRule
{
bool IsBroken();
string Message { get; }
}
@@ -0,0 +1,9 @@
namespace Vizhvizh.BuildingBlocks.Domain.Exceptions;
public class ValueObjectValidationException : Exception
{
public ValueObjectValidationException(string message)
:base(message)
{
}
}
@@ -0,0 +1,54 @@
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
namespace Vizhvizh.BuildingBlocks.Domain.Extensions;
public static class EnumExtensions
{
// Cache to store display names of enum values
private static readonly ConcurrentDictionary<Enum, string> DisplayNameCache = new();
/// <summary>
/// Gets an attribute on an enum field value.
/// </summary>
/// <typeparam name="T">The type of the attribute to retrieve.</typeparam>
/// <param name="enumValue">The enum value.</param>
/// <returns>
/// The attribute of the specified type or null.
/// </returns>
public static T GetAttributeOfType<T>(this Enum enumValue) where T : Attribute
{
var type = enumValue.GetType();
// Use GetField to get the field info for the enum value
var memInfo = type.GetField(enumValue.ToString(), BindingFlags.Public | BindingFlags.Static);
if (memInfo == null)
return null;
// Retrieve the custom attributes of type T
var attributes = memInfo.GetCustomAttributes<T>(false);
return attributes.FirstOrDefault();
}
/// <summary>
/// Gets the enum display name.
/// </summary>
/// <param name="enumValue">The enum value.</param>
/// <returns>
/// Use <see cref="DisplayAttribute"/> if it exists.
/// Otherwise, use the standard string representation.
/// </returns>
public static string GetDisplayName(this Enum enumValue)
{
// Retrieve the display name from the cache if it exists
return DisplayNameCache.GetOrAdd(enumValue, e =>
{
// Get the DisplayAttribute
var attribute = e.GetAttributeOfType<DisplayAttribute>();
// Return the DisplayAttribute name if it exists, otherwise return the enum's string representation
return attribute == null ? e.ToString() : attribute.Name;
});
}
}
@@ -0,0 +1,7 @@
namespace Vizhvizh.BuildingBlocks.Domain;
public interface IAggregateRoot
{
}
@@ -0,0 +1,12 @@
using Vizhvizh.BuildingBlocks.Domain.Contract;
namespace Vizhvizh.BuildingBlocks.Domain
{
public interface IDomainEvent : INotification
{
Guid Id { get; }
DateTime OccurredOn { get; }
}
}
@@ -0,0 +1,10 @@
namespace Vizhvizh.BuildingBlocks.Domain;
public interface IRepositoryBase<TDomain, TId>
where TDomain : Entity<TId> where TId : ITypeIdValueBase
{
Task CreateAsync(TDomain entity, CancellationToken cancellationToken = default);
Task UpdateAsync(TDomain entity, CancellationToken cancellationToken = default);
Task DeleteAsync(TId id, CancellationToken cancellationToken = default);
Task<TDomain> GetByIdAsync(TId id, CancellationToken cancellationToken = default);
}
@@ -0,0 +1,6 @@
namespace Vizhvizh.BuildingBlocks.Domain;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class IgnoreMemberAttribute : Attribute
{
}
@@ -0,0 +1,59 @@
namespace Vizhvizh.BuildingBlocks.Domain;
public abstract class TypedIdValueBase<T> : IEquatable<TypedIdValueBase<T>> , ITypeIdValueBase
{
public T Value { get; }
protected TypedIdValueBase(T value)
{
if (EqualityComparer<T>.Default.Equals(value, default(T)))
{
throw new InvalidOperationException($"Id value cannot be empty ! : id is {value}");
}
Value = value;
}
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
return obj is TypedIdValueBase<T> other && Equals(other);
}
public override int GetHashCode()
{
return Value!.GetHashCode();
}
public bool Equals(TypedIdValueBase<T>? other)
{
return EqualityComparer<T>.Default.Equals(this.Value, other.Value);
}
public static bool operator ==(TypedIdValueBase<T>? obj1, TypedIdValueBase<T>? obj2)
{
if (object.Equals(obj1, null))
{
if (object.Equals(obj2, null))
{
return true;
}
return false;
}
return obj1.Equals(obj2);
}
public static bool operator !=(TypedIdValueBase<T>? x, TypedIdValueBase<T>? y)
{
return !(x == y);
}
}
public interface ITypeIdValueBase { }
@@ -0,0 +1,123 @@
using System.Reflection;
using Vizhvizh.BuildingBlocks.Domain.Exceptions;
namespace Vizhvizh.BuildingBlocks.Domain;
public abstract class ValueObject : IEquatable<ValueObject>
{
private List<PropertyInfo> _properties;
private List<FieldInfo> _fields;
public static bool operator ==(ValueObject? obj1, ValueObject? obj2)
{
if (object.Equals(obj1, null))
{
if (object.Equals(obj2, null))
{
return true;
}
return false;
}
return obj1.Equals(obj2);
}
public static bool operator !=(ValueObject? obj1, ValueObject? obj2)
{
return !(obj1 == obj2);
}
public bool Equals(ValueObject? obj)
{
return Equals(obj as object);
}
public override bool Equals(object? obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return GetProperties().All(p => PropertiesAreEqual(obj, p))
&& GetFields().All(f => FieldsAreEqual(obj, f));
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
foreach (var prop in GetProperties())
{
var value = prop.GetValue(this, null);
hash = HashValue(hash, value);
}
foreach (var field in GetFields())
{
var value = field.GetValue(this);
hash = HashValue(hash, value);
}
return hash;
}
}
protected static void CheckRule(IBusinessRule rule)
{
if (rule.IsBroken())
{
throw new BusinessRuleValidationException(rule);
}
}
private bool PropertiesAreEqual(object obj, PropertyInfo p)
{
return object.Equals(p.GetValue(this, null), p.GetValue(obj, null));
}
private bool FieldsAreEqual(object obj, FieldInfo f)
{
return object.Equals(f.GetValue(this), f.GetValue(obj));
}
private IEnumerable<PropertyInfo> GetProperties()
{
if (this._properties == null)
{
this._properties = GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.GetCustomAttribute(typeof(IgnoreMemberAttribute)) == null)
.ToList();
// Not available in Core
// !Attribute.IsDefined(p, typeof(IgnoreMemberAttribute))).ToList();
}
return this._properties;
}
private IEnumerable<FieldInfo> GetFields()
{
if (this._fields == null)
{
this._fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(p => p.GetCustomAttribute(typeof(IgnoreMemberAttribute)) == null)
.ToList();
}
return this._fields;
}
private int HashValue(int seed, object value)
{
var currentHash = value?.GetHashCode() ?? 0;
return (seed * 23) + currentHash;
}
}
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>