Repository navigation
ExternalTypeResolution fr
🌐 Cette page en : English · Português · Español · Français · Deutsch
Le compilateur eQuantic.UI résout les types définis dans des fichiers externes au sein du même projet. Les composants référencent des modèles, des DTO et d'autres classes sans qu'elles aient à se trouver dans le même fichier : le compilateur travaille contre la Compilation Roslyn complète du projet, qui comprend tous les fichiers source et les références.
// Models/User.cs
public class User
{
public string Name { get; set; }
public string Email { get; set; }
}
// Pages/UserProfile.cs
[Page("/profile")]
public class UserProfile : StatefulComponent
{
private User _currentUser; // ✅ Le type 'User' est entièrement résolu
protected override HtmlNode Render()
{
return Text(_currentUser.Name); // ✅ Se convertit en : this._currentUser.name
}
}Un modèle sémantique complet compte parce que la conversion de l'accès aux membres dépend de la connaissance du type du receveur : avec lui, _currentUser.Name s'abaisse en this._currentUser.name ; sans lui, le compilateur ne peut pas distinguer une propriété d'une variable locale ni choisir le bon mappage de méthode.
using eQuantic.UI.Compiler;
using eQuantic.UI.Compiler.Services;
// Obtenir la compilation complète du projet
var compilation = await ProjectCompilationHelper
.GetProjectCompilationAsync("path/to/MyApp.csproj");
// Créer le compilateur et poser la compilation du projet
var compiler = new ComponentCompiler();
compiler.SetProjectCompilation(compilation);
// Maintenant compilez les composants : les types externes seront résolus
var results = compiler.CompileFile("Pages/UserProfile.cs");Utile dans des tâches MSBuild où MSBuildWorkspace peut ne pas être disponible :
using eQuantic.UI.Compiler.Services;
// Obtenir tous les fichiers .cs du projet
var sourceFiles = ProjectCompilationHelper
.GetProjectSourceFiles("path/to/MyApp");
// Obtenir les références d'assemblys
var assemblyPaths = new[]
{
"path/to/eQuantic.UI.Primitives.dll",
"path/to/other-dependencies.dll"
};
// Créer la compilation depuis les sources
var compilation = ProjectCompilationHelper.CreateCompilationFromSources(
sourceFiles,
assemblyPaths,
"MyApp");
var compiler = new ComponentCompiler();
compiler.SetProjectCompilation(compilation);Revenir au mode de compilation minimale (fichiers isolés) :
compiler.ClearProjectCompilation();┌─────────────────────────────────────────┐
│ Compilation du projet MSBuild │
│ - Tous les .cs du projet │
│ - Tous les assemblys référencés │
│ - Information de types complète │
└────────────┬────────────────────────────┘
│
↓ SetProjectCompilation()
┌────────────────────────────────────────┐
│ SemanticModelProvider │
│ - Garde la compilation du projet │
│ - Renvoie un SemanticModel par fichier│
└────────────┬───────────────────────────┘
│
↓ GetSemanticModel(tree)
┌────────────────────────────────────────┐
│ CSharpToJsConverter │
│ - Utilise le SemanticModel pour les types │
│ - Convertit _currentUser.Name → name │
└────────────────────────────────────────┘
-
SemanticModelProvider(SemanticModelProvider.cs)-
SetProjectCompilation(Compilation)- pose la compilation complète du projet -
GetSemanticModel(SyntaxTree)- renvoie le modèle sémantique avec l'information de types complète
-
-
ProjectCompilationHelper(ProjectCompilationHelper.cs)-
GetProjectCompilationAsync(string)- charge depuis le .csproj -
CreateCompilationFromSources(...)- construit depuis des fichiers source -
GetProjectSourceFiles(string)- trouve tous les fichiers .cs
-
-
ComponentCompiler(ComponentCompiler.cs)-
SetProjectCompilation(Compilation)- active la résolution des types externes -
ClearProjectCompilation()- revient au mode isolé
-
Models/Product.cs :
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public bool InStock { get; set; }
}Pages/ProductCard.cs :
[Component]
public class ProductCard : StatelessComponent
{
public Product Item { get; set; }
protected override HtmlNode Build()
{
return Container(
Heading(Item.Name),
Text($"${Item.Price:F2}"),
Text(Item.InStock ? "In Stock" : "Out of Stock")
);
}
}JavaScript généré (avec la compilation du projet) :
class ProductCard extends StatelessComponent {
build() {
return Container([
Heading(this.item.name),
Text(`$${this.item.price.toFixed(2)}`),
Text(this.item.inStock ? 'In Stock' : 'Out of Stock')
]);
}
}Models/Address.cs :
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
}Models/Customer.cs :
public class Customer
{
public string Name { get; set; }
public string Email { get; set; }
public Address ShippingAddress { get; set; }
}Pages/CheckoutPage.cs :
[Page("/checkout")]
public class CheckoutPage : StatefulComponent
{
private Customer _customer;
protected override HtmlNode Render()
{
return Container(
Text($"Customer: {_customer.Name}"),
Text($"Email: {_customer.Email}"),
Text($"Shipping: {_customer.ShippingAddress.City}, {_customer.ShippingAddress.ZipCode}")
);
}
}Tous les accès aux propriétés sont correctement résolus et convertis en JavaScript.
Les tests vérifient que la résolution des types externes marche correctement :
[Fact]
public void SemanticModel_WithProjectCompilation_CanResolveExternalTypes()
{
// Créer la compilation avec User et le composant
var userTree = CSharpSyntaxTree.ParseText("public class User { ... }");
var componentTree = CSharpSyntaxTree.ParseText("public class UserProfile { ... }");
var compilation = CSharpCompilation.Create("Test", new[] { userTree, componentTree }, ...);
var provider = new SemanticModelProvider();
provider.SetProjectCompilation(compilation);
var semanticModel = provider.GetSemanticModel(componentTree);
// Affirmer : le type User est résolu
var userType = semanticModel.Compilation.GetTypeByMetadataName("User");
userType.Should().NotBeNull();
}Voir ExternalTypeResolutionTests.cs pour la suite de tests complète.
- Sans
SetProjectCompilation(): compilation minimale, donc chaque fichier est résolu isolément - Avec
SetProjectCompilation(): résolution des types de tout le projet
Surcoût minimal :
- La compilation du projet est créée une fois, au build
- Elle est partagée par tous les fichiers de composants
- Aucune pénalité de compilation par fichier
Économe en mémoire :
- Une seule instance de compilation
- Réutilise l'infrastructure Roslyn existante
-
Demande une compilation avant la compilation des composants : le projet doit être compilé (ou au moins parsé) avant de lancer le compilateur de composants.
-
Disponibilité de MSBuildWorkspace :
GetProjectCompilationAsyncdemande les API MSBuild, qui peuvent ne pas être disponibles dans tous les contextes. UtilisezCreateCompilationFromSourcesen repli. -
Code généré : les fichiers auto-générés dans
obj/sont exclus pour éviter les conflits.
- Les composants référencent des classes d'autres fichiers ; l'information de types complète est disponible pendant la compilation, donc la génération de JavaScript pour les membres de types externes est correcte.
- Le build du SDK alimente le compilateur avec les vraies références d'assemblys du projet (
--refs), donc les types de receveur se résolvent même par-delà les frontières de paquets.
var compilation = await ProjectCompilationHelper.GetProjectCompilationAsync(projectPath);
compiler.SetProjectCompilation(compilation);🏁 Commencer ici
🏗️ Architecture
- Vue d'ensemble de l'architecture
- Composants write-once
- Surface déclarative
- Architecture des paquets
- Composants
- Styles
- Localisation
- Analytics et GTM
📱 Write-once
- Moteur Photon
- Design System
- Capacités
- Stockage
- Formulaires
- Éditeur de code
- Markdown
- Mermaid
- Rendu des e-mails
⚙️ Compilation
- Compilateur
- Fonctionnalités C# prises en charge
- Résolution des types externes
- Flux de build
- Diagnostics
⚡ Runtime
🔌 Serveur
🎨 Écosystème
- Image · Graphiques · Icônes · Lottie
🚀 Développement