如何将Aurelia验证规则迁移至单例Repository中?
Great question—you’re absolutely right that defining validation rules in the Entity constructor leads to redundant execution when creating multiple instances. Since your InviteRepository is a singleton, it’s the perfect place to register these rules once instead of every time an Invite instance is created. Here’s how to implement this:
Step 1: Refactor the Invite Entity
First, remove the validation rule setup from the Invite constructor—we no longer need this code running for each instance. Also, fix the duplicate @autoinject decorator in your original code:
import { type, Entity, validatedResource, resource, repository } from 'aurelia-orm'; import { InviteRepository } from 'data/service/invite-repository'; import { autoinject } from 'aurelia-framework'; @resource() @repository(InviteRepository) @validatedResource() @autoinject() export class Invite extends Entity { id: number; firstName = null; lastName = null; email = null; message = null; invitedOn: Date; constructor() { super(); // Validation rules are now registered in the repository } validateFirstName(name: string): boolean { // Get the typed repository instance to call its validation logic return this.getRepository(InviteRepository).validateFirstName(name); } }
Step 2: Update the Singleton InviteRepository
Mark your repository as a singleton using Aurelia’s @singleton() decorator, then register the validation rules once in its constructor. This ensures the rule setup code runs exactly once when the repository is first initialized:
import { Repository } from 'aurelia-orm'; import { Invite } from './invite'; import { autoinject, singleton } from 'aurelia-framework'; import { ValidationRules } from 'aurelia-validation'; @singleton() @autoinject() export class InviteRepository extends Repository<Invite> { constructor() { super(Invite); // Register validation rules once during repository initialization this.setupValidationRules(); } private setupValidationRules(): void { ValidationRules .ensure('firstName') .required() .satisfies((value, obj: Invite) => obj.validateFirstName(value)) .withMessage("First Name must be Greg") .ensure('lastName').required() .ensure('email').email() .on(Invite); } validateFirstName(name: string): boolean { // Your centralized validation logic goes here return name === 'Greg'; } }
Why This Works
- Singleton Repository: The
@singleton()decorator ensures only one instance ofInviteRepositoryis created. ThesetupValidationRulesmethod runs once during initialization, not for everyInviteinstance. - Class-Level Validation:
ValidationRules.on(Invite)registers rules for the entireInviteclass, so all instances inherit these rules without re-registering them. - Eliminated Redundancy: When you create 100
Inviteinstances, the rule setup code doesn’t run again—only the actual validation checks execute when needed.
Key Notes
- Keep using the
@validatedResource()decorator on yourInviteentity—it works seamlessly with the class-level rules registered in the repository. - The
satisfiesclause delegates to the entity’svalidateFirstNamemethod, which calls the repository’s centralized validation logic, keeping your code organized.
内容的提问来源于stack exchange,提问作者Greg Gum

