init project

This commit is contained in:
2021-02-23 09:51:50 +08:00
commit f7384b9afc
35 changed files with 938 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
using Domain.SeedWork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Domain.AggregateModel.AppAggregate
{
public class App : IAggregateRoot
{
public int Id { get; private set; }
public string AppKey { get;private set; }
public string BaseUrl { get; private set; }
public string Remarks { get;private set; }
private App() { }
public App(string appKey,string remarks)
{
AppKey = appKey;
Remarks = remarks;
}
}
}

View File

@@ -0,0 +1,15 @@
using Domain.SeedWork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Domain.AggregateModel.AppAggregate
{
public interface IAppRepository:IRepository<App>
{
void Add(App app);
Task<App> GetAsync(int id);
}
}

View File

@@ -0,0 +1,16 @@
using Domain.SeedWork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Domain.AggregateModel.LinkAggregate
{
public interface ILinkRepository:IRepository<Link>
{
void Add(Link link);
Task<Link> GetAsync(string shortCode);
}
}

View File

@@ -0,0 +1,61 @@
using Base62;
using Domain.SeedWork;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Domain.AggregateModel.LinkAggregate
{
public class Link:IAggregateRoot
{
/// <summary>
/// 非自增主键
/// </summary>
public string ShortCode { get; private set; }
public string BaseUrl { get; private set; }
public string SuffixUrl { get; private set; }
public string FullUrl { get; private set; }
public int AppId { get; private set; }
public DateTime Time { get; private set; }
private Link()
{
}
/// <summary>
/// 创建一条新的短链接
/// </summary>
/// <param name="baseUrl"></param>
/// <param name="suffixUrl"></param>
/// <param name="appId">分配的应用id</param>
public Link(string baseUrl,string suffixUrl,int appId)
{
BaseUrl = baseUrl;
SuffixUrl = suffixUrl;
FullUrl = new Uri(new Uri(baseUrl),suffixUrl).ToString();
AppId = appId;
Time = DateTime.Now;
CalculateShortCode();
}
/// <summary>
/// 根据值计算短链字段
/// </summary>
/// <returns></returns>
private void CalculateShortCode()
{
string code;
using (var md5 = MD5.Create())
{
var result = md5.ComputeHash(Encoding.UTF8.GetBytes(FullUrl));
var res = new[] { BitConverter.ToInt64(result, 0) ,BitConverter.ToInt64(result,8)};
//任意取其中一条即可
code = res[new Random().Next(0,1)].ToBase62();
}
ShortCode = code;
}
}
}

12
Domain/Domain.csproj Normal file
View File

@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Base62-Net" Version="1.2.157201" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
</ItemGroup>
</Project>

92
Domain/SeedWork/Entity.cs Normal file
View File

@@ -0,0 +1,92 @@
using MediatR;
using System;
using System.Collections.Generic;
namespace Domain.SeedWork
{
public abstract class Entity
{
int? _requestedHashCode;
int _Id;
public virtual int Id
{
get
{
return _Id;
}
protected set
{
_Id = value;
}
}
private List<INotification> _domainEvents;
public IReadOnlyCollection<INotification> DomainEvents => _domainEvents?.AsReadOnly();
public void AddDomainEvent(INotification eventItem)
{
_domainEvents = _domainEvents ?? new List<INotification>();
_domainEvents.Add(eventItem);
}
public void RemoveDomainEvent(INotification eventItem)
{
_domainEvents?.Remove(eventItem);
}
public void ClearDomainEvents()
{
_domainEvents?.Clear();
}
public bool IsTransient()
{
return Id == default;
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is Entity))
return false;
if (ReferenceEquals(this, obj))
return true;
if (this.GetType() != obj.GetType())
return false;
Entity item = (Entity)obj;
if (item.IsTransient() || this.IsTransient())
return false;
else
return item.Id == this.Id;
}
public override int GetHashCode()
{
if (!IsTransient())
{
if (!_requestedHashCode.HasValue)
_requestedHashCode = this.Id.GetHashCode() ^ 31; // XOR for random distribution (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx)
return _requestedHashCode.Value;
}
else
return base.GetHashCode();
}
public static bool operator ==(Entity left, Entity right)
{
if (Object.Equals(left, null))
return (Object.Equals(right, null)) ? true : false;
else
return left.Equals(right);
}
public static bool operator !=(Entity left, Entity right)
{
return !(left == right);
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Domain.SeedWork
{
public abstract class Enumeration : IComparable
{
public string Name { get; private set; }
public int Id { get; private set; }
protected Enumeration(int id, string name)
{
Id = id;
Name = name;
}
public override string ToString() => Name;
public static IEnumerable<T> GetAll<T>() where T : Enumeration
{
var fields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
return fields.Select(f => f.GetValue(null)).Cast<T>();
}
public override bool Equals(object obj)
{
var otherValue = obj as Enumeration;
if (otherValue == null)
return false;
var typeMatches = GetType().Equals(obj.GetType());
var valueMatches = Id.Equals(otherValue.Id);
return typeMatches && valueMatches;
}
public override int GetHashCode() => Id.GetHashCode();
public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue)
{
var absoluteDifference = Math.Abs(firstValue.Id - secondValue.Id);
return absoluteDifference;
}
public static T FromValue<T>(int value) where T : Enumeration
{
var matchingItem = Parse<T, int>(value, "value", item => item.Id == value);
return matchingItem;
}
public static T FromDisplayName<T>(string displayName) where T : Enumeration
{
var matchingItem = Parse<T, string>(displayName, "display name", item => item.Name == displayName);
return matchingItem;
}
private static T Parse<T, K>(K value, string description, Func<T, bool> predicate) where T : Enumeration
{
var matchingItem = GetAll<T>().FirstOrDefault(predicate);
if (matchingItem == null)
throw new InvalidOperationException($"'{value}' is not a valid {description} in {typeof(T)}");
return matchingItem;
}
public int CompareTo(object other) => Id.CompareTo(((Enumeration)other).Id);
}
}

View File

@@ -0,0 +1,6 @@
namespace Domain.SeedWork
{
public interface IAggregateRoot
{
}
}

View File

@@ -0,0 +1,7 @@
namespace Domain.SeedWork
{
public interface IRepository<T> where T : IAggregateRoot
{
IUnitOfWork UnitOfWork { get; }
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Domain.SeedWork
{
public interface IUnitOfWork : IDisposable
{
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken));
}
}

View File

@@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.Linq;
namespace Domain.SeedWork
{
public abstract class ValueObject
{
protected static bool EqualOperator(ValueObject left, ValueObject right)
{
if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
{
return false;
}
return ReferenceEquals(left, null) || left.Equals(right);
}
protected static bool NotEqualOperator(ValueObject left, ValueObject right)
{
return !(EqualOperator(left, right));
}
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType())
{
return false;
}
var other = (ValueObject)obj;
return this.GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
}
public override int GetHashCode()
{
return GetEqualityComponents()
.Select(x => x != null ? x.GetHashCode() : 0)
.Aggregate((x, y) => x ^ y);
}
public ValueObject GetCopy()
{
return this.MemberwiseClone() as ValueObject;
}
}
}