70 lines
3.2 KiB
Markdown
70 lines
3.2 KiB
Markdown
# Architecture
|
|
|
|
## Dependency Graph
|
|
|
|
```
|
|
AyCode.Utils (zero dependencies)
|
|
↑
|
|
AyCode.Interfaces → AyCode.Entities → AyCode.Models
|
|
↑ ↑ ↑
|
|
AyCode.Core ─────────────┘ │
|
|
↑ │
|
|
AyCode.Database ────────────────────────────┘
|
|
↑
|
|
AyCode.Services ← AyCode.Services.Server
|
|
```
|
|
|
|
**Rule:** Dependencies flow upward only. Lower layers never reference higher layers.
|
|
|
|
## Project Roles
|
|
|
|
### Foundation Layer
|
|
- **AyCode.Utils** — Zero-dependency utilities. String/DateTime extensions, lock wrappers.
|
|
- **AyCode.Interfaces** — Pure interfaces. `IId<T>` is the root abstraction.
|
|
- **AyCode.Entities** — Abstract generic entity classes. Never instantiated directly.
|
|
- **AyCode.Models** — DTOs and view models for service boundaries.
|
|
|
|
### Core Layer
|
|
- **AyCode.Core** — Serializers (Binary, JSON, Toon), compression (Brotli, GZip, LZ4), logging framework, constants, validation.
|
|
- **AyCode.Core.Serializers.SourceGenerator** — Roslyn incremental generator. Targets netstandard2.0. Generates `IGeneratedBinaryWriter` / `IGeneratedBinaryReader` for `[AcBinarySerializable]` types.
|
|
|
|
### Data Layer
|
|
- **AyCode.Database** — EF Core with generic DAL pattern. Session for reads, Transaction for writes. DAL pooling via `PooledDal`.
|
|
|
|
### Service Layer
|
|
- **AyCode.Services** — Client-side: SignalR client, login service, loggers.
|
|
- **AyCode.Services.Server** — Server-side: SignalR hub with custom binary protocol, email (SendGrid), JWT auth.
|
|
- **AyCode.Models.Server/DynamicMethods** — Reflection-based tag→method dispatch used by the SignalR hub.
|
|
|
|
> **SignalR Dispatch:** Both directions use a single method `OnReceiveMessage(int messageTag, int? requestId, SignalParams signalParams, object data)` with integer tag-based routing instead of standard Hub methods. Write path: zero-copy via `AcBinarySerializer.Serialize(value, output)` directly to pipe. Read path: protocol eagerly deserializes `data` to typed object via `SignalParams.SignalDataType`, or returns raw `byte[]` for `IsRawBytesData`/byte[] fast-path. See `AyCode.Services/docs/SIGNALR.md` for full details.
|
|
|
|
### Server Extensions
|
|
- **AyCode.Core.Server**, **AyCode.Interfaces.Server**, **AyCode.Entities.Server**, **AyCode.Models.Server** — Server-only additions that don't belong in shared code.
|
|
|
|
## Serialization Architecture
|
|
|
|
Three serializers share a common infrastructure but serve different goals:
|
|
|
|
| Serializer | Primary Goal | Use Case |
|
|
|---|---|---|
|
|
| **AcBinary** | Speed | Wire protocol, SignalR, storage |
|
|
| **AcJson** | Compatibility | REST APIs, debugging, interop |
|
|
| **Toon** | LLM Accuracy | AI context, schema documentation |
|
|
|
|
## Generic Entity Pattern
|
|
|
|
Entities use composition via generic type parameters:
|
|
|
|
```csharp
|
|
// Interface layer
|
|
interface IAcUser<TProfile, TCompany> : IId<Guid> { ... }
|
|
|
|
// Entity layer (abstract)
|
|
abstract class AcUser<TProfile, TCompany, TUserToCompany, TAddress> { ... }
|
|
|
|
// Consuming project (concrete)
|
|
class User : AcUser<Profile, Company, UserToCompany, Address> { ... }
|
|
```
|
|
|
|
This allows the framework to define relationships without knowing concrete types.
|