Skip to content

Services Overview - Service System General Overview

General introduction to the Dependency Injection (DI) service system of XCon Widget Framework.

🎯 What is it?

The service system is a Dependency Injection solution used to manage inter-component dependencies in your application. It provides easy and safe usage with modern TypeScript decorators.

🏗️ Basic Concepts

Service

Classes that contain shared business logic in your application. For example, data management, API calls, configuration, etc.

Dependency Injection (DI)

The process of automatically providing the services that components need.

Scope

Determines when and how services are created:

  • Singleton: Single instance, throughout the entire application
  • Transient: New instance for each use
  • Scoped: Same instance within a specific scope

📦 Quick Start

1. Defining a Service

typescript
import { xinjectable } from '@xcons/widget';

@xinjectable()
export class DataService {
  getData() {
    return ['item1', 'item2', 'item3'];
  }
}

2. Using a Service

typescript
import { xinject } from '@xcons/widget';

export class UserComponent {
  @xinject(DataService)
  private dataService!: DataService;

  loadData() {
    const data = this.dataService.getData();
    console.log(data);
  }
}

🔧 Main Decorators

Service Definition Decorators

typescript
@xinjectable()      // Default (singleton)
@xsingleton()       // Single instance
@xtransient()       // New each time
@xscoped()          // Scope-based

Injection Decorator

typescript
@xinject(ServiceClass)  // Property injection

🔄 Lifecycle Hooks

Manage the initialization and termination processes of services:

typescript
import { xinjectable, OnServiceInit, OnServiceDestroy } from '@xcons/widget';

@xinjectable()
export class DatabaseService implements OnServiceInit, OnServiceDestroy {
  async onServiceInit() {
    // When service is initialized
    console.log('Establishing connection...');
  }

  async onServiceDestroy() {
    // When service is terminated
    console.log('Closing connection...');
  }
}

🎪 Token System

Token usage for interfaces and values:

typescript
import { createServiceToken, registerValue } from '@xcons/widget';

// Creating a token
const API_URL = createServiceToken<string>('API_URL');

// Registering a value
registerValue(API_URL, 'https://api.example.com');

// Using
export class ApiService {
  @xinject(API_URL)
  private apiUrl!: string;
}

🧪 Test Support

Easy testing with mock services:

typescript
import { ServiceRegistry } from '@xcons/widget';

// Mock for testing
class MockDataService {
  getData() {
    return ['mock-data'];
  }
}

// Test setup
beforeEach(() => {
  ServiceRegistry.getInstance().clear();
  registerService(MockDataService, { token: DataService });
});

🛠️ Basic API

ServiceRegistry

typescript
import { ServiceRegistry } from '@xcons/widget';

const registry = ServiceRegistry.getInstance();

// Registering a service
registry.registerService(MyService);

// Getting a service
const service = registry.getService(MyService);

// Clearing
registry.clear();
registry.clearScope('scoped');

ServiceInjector

typescript
import { ServiceInjector } from '@xcons/widget';

const injector = ServiceInjector.getInstance();

// Service injection
const service = injector.inject(MyService);

// Check
const canInject = injector.canInject(MyService);

📋 Usage Scenarios

Data Management

typescript
@xsingleton()
export class StateService {
  private state = {};
  
  setState(key: string, value: any) {
    this.state[key] = value;
  }
}

API Operations

typescript
@xinjectable()
export class ApiService {
  @xinject(HttpClient)
  private http!: HttpClient;
  
  fetchUsers() {
    return this.http.get('/users');
  }
}

Configuration

typescript
@xsingleton()
export class ConfigService {
  private config = { /* ... */ };
  
  get(key: string) {
    return this.config[key];
  }
}

🔗 Detailed Documentation

Detailed documentation for each topic:

✨ Advantages

  • Loose Coupling: Components are independent of each other
  • Reusability: Services can be used everywhere
  • Testability: Easy testing with mock services
  • Type Safety: Safe type checking with TypeScript
  • Automatic Management: Lifecycle and dependencies are managed automatically