编辑 | blame | 历史 | 原始文档

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build Commands

# Build entire solution
dotnet build WIDESEAWCS_Server.sln

# Build and run server
cd WIDESEAWCS_Server
dotnet run

# Run tests
cd WIDESEAWCS_Tests
dotnet test

Architecture Overview

This is a WCS (Warehouse Control System) built with ASP.NET Core 6.0, using:
- Autofac for DI with automatic service discovery via IDependency marker interface
- Quartz.NET for scheduled job execution (device communication loops)
- SqlSugar ORM for database access
- Redis (via WIDESEAWCS_RedisService) for distributed caching with L1+L2 hybrid pattern
- StackExchange.Redis for Redis operations
- TCP Socket Server for real-time device communication
- HslCommunication library for PLC/hardware communication

Project Structure

WIDESEAWCS_Server/          # Main ASP.NET Core API server
WIDESEAWCS_Core/            # Core infrastructure: base classes, DI, extensions, middleware
WIDESEAWCS_Model/           # Data models and DTOs
WIDESEAWCS_Communicator/    # Hardware communication drivers (Siemens, Omron, Modbus, etc.)
WIDESEAWCS_QuartzJob/       # Job scheduling infrastructure and device abstractions
WIDESEAWCS_Tasks/           # Quartz job implementations (device communication loops)
WIDESEAWCS_RedisService/    # Redis services: Cache, Lock, Counter, PubSub, etc.
WIDESEAWCS_*Repository/     # Data access layer implementations
WIDESEAWCS_*Service/        # Business service layer
WIDESEAWCS_Tests/           # Unit tests

Dependency Injection - IDependency Pattern

Services are automatically registered with Autofac by implementing the empty IDependency marker interface:

// In WIDESEAWCS_Core/IDependency.cs
public interface IDependency { }

// Your service gets auto-registered
public class MyService : IDependency  // Automatically registered as scoped
{
    // ...
}

Registration happens in AutofacModuleRegister which scans all project assemblies for IDependency implementations.

Important: When adding services to IServiceCollection (e.g., in Program.cs), they can be overridden by Autofac's registrations. Use Remove() to replace existing registrations:

// In RedisServiceSetup.cs - removes MemoryCacheService before adding HybridCacheService
var existing = services.FirstOrDefault(d => d.ServiceType == typeof(ICacheService));
if (existing != null) services.Remove(existing);

Caching - ICacheService

The system uses a hybrid L1 (Memory) + L2 (Redis) cache pattern via ICacheService. Three implementations exist:
- MemoryCacheService - Memory only
- RedisCacheService - Redis only
- HybridCacheService - L1+L2 with fallback (default when Redis enabled)

Common methods:
- Add/AddObject - Add cache
- Get/Get<T> - Retrieve cached values
- Remove - Delete single key
- RemoveByPrefix/RemoveByPattern - Bulk delete by pattern
- GetOrAdd<T> - Retrieve or add with factory
- TryAdd/TryUpdate/TryUpdateIfChanged - ConcurrentDictionary-style operations

Configuration in appsettings.json:
json "RedisConfig": { "Enabled": true, "ConnectionString": "127.0.0.1:6379,password=P@ssw0rd,...", "KeyPrefix": "wcs:" }

Quartz Jobs - Device Communication

Jobs inherit from JobBase and implement Quartz's IJob:

public class MyDeviceJob : JobBase, IJob
{
    public async Task Execute(IJobExecutionContext context)
    {
        ExecuteJob(context, async () => {
            // Job logic here
            WriteDebug("MyDevice", "Debug message");
            WriteInfo("MyDevice", "Info message");
        });
    }
}

Jobs are registered dynamically via SchedulerCenterServer using device info from Dt_DeviceInfo table.

Device types:
- IStackerCrane - Stacker cranes
- IConveyorLine - Conveyor lines
- IShuttleCar - Shuttle cars
- IRobot - Robot cranes

Hardware Communication

Communicator classes wrap the HslCommunication library:
- SiemensS7Communicator / SiemensS7200SmartCommunicator - Siemens PLCs
- OmronEtherNetCommunicator - Omron PLCs
- ModbusTcpCommunicator - Modbus TCP
- SerialPortCommunicator - Serial port devices

TCP Socket Server

The TcpSocketServer (port 2000) handles real-time device communication:
- Managed as a Singleton with SocketServerHostedService
- Client connections stored in ConcurrentDictionary<string, TcpClient>
- Messages handled via OnDataReceived event

Configuration Settings

Key settings in appsettings.json:
- "urls": "http://*:9292" - Server port
- "QuartzJobAutoStart": true - Auto-start scheduled jobs
- "SocketServer:Enabled": true - Enable TCP server
- "RedisConfig:Enabled": true - Enable Redis caching
- "LogAOPEnable": false - Enable AOP logging
- "DBType": "SqlServer" - Database type

Service Layer Pattern

Services follow a layered pattern:
- Interface in WIDESEAWCS_IService/ (e.g., ITaskInfoService)
- Implementation in WIDESEAWCS_Service/ (e.g., TaskInfoService)
- Both implement IDependency for auto-registration

Base Classes

  • ServiceBase<T, TKey> - Base service with CRUD operations
  • RepositoryBase<TEntity> - Base repository with SqlSugar ORM
  • ApiBaseController - Base API controller with common functionality
  • JobBase - Base Quartz job with logging helpers

Adding New Features

  1. New Service: Create interface in I*Service/ and class in *Service/, implement IDependency
  2. New Job: Inherit from JobBase and IJob in WIDESEAWCS_Tasks/
  3. New Device Type: Add interface in WIDESEAWCS_QuartzJob/Device/ and implement

Important Notes

  • The application uses CamelCase JSON serialization
  • All services use scoped lifetime by default via Autofac
  • Redis connection uses Lazy initialization - first access triggers connection
  • Use ConsoleHelper.WriteSuccessLine() / WriteErrorLine() for console output in jobs
  • TCP Socket server runs independently of the HTTP API