2010-04-06 3 views

Répondre

0

En C/C++, la définition de classe est présente dans un fichier d'en-tête .h. Cela vous donne la possibilité de référencer des informations sur une classe (si nécessaire, par exemple, lorsque vous souhaitez hériter de cette classe) sans avoir besoin de fournir un fichier avec les informations d'implémentation. L'inconvénient est la duplication de code (l'implémentation dans le fichier .cpp doit répéter la plupart des informations dans le fichier .h). Dans le monde .NET, la conception est différente: un assemblage contient à la fois le code de la classe (code octet CLR) ainsi que toutes les métadonnées (nom de classe, informations sur ses membres, etc.) nécessaires pour, par exemple, hériter de cette classe.

Une conséquence de cette conception est que, pour utiliser une classe définie dans l'assembly A qui hérite d'une classe dans l'assembly B, .NET a besoin d'assemblages A et B. Ou plus génériquement: si vous utilisez quelque chose d'un assembly donné (une classe, une énumération, une struct), directement ou indirectement, vous devez référencer cet assembly.

Je ne suis pas sûr de ce que vous voulez éviter. Si vous décidez de diviser votre code en deux assemblées comme vous l'avez décrit, il n'y a aucun moyen de faire référence aux deux. Il y a, bien sûr, différentes façons de structurer votre code, mais vous ne savez pas quel objectif vous essayez d'atteindre en divisant le code en 2 assemblées, il est impossible de faire une suggestion utile.

+0

L'objectif était de créer un wrapper qui protégerait les utilisateurs finaux des modifications de la couche sous-jacente. Ce wrapper référencerait la base. Donc, si l'utilisateur doit référencer la base, il n'est pas complètement protégé. Je comprends comment les assemblages .Net sont construits mais je me demandais s'il y avait un moyen de contourner cela (une idée folle était d'inverser la classe de base à l'exécution par réflexion, pas sûr que cela soit possible). – Mrchief

1

Ce que vous décrivez est partiellement possible. Vous pouvez éliminer le besoin pour eux de référencer explicitement l'assembly masqué, mais cet assembly sera toujours extrait au moment de la compilation et requis lors de l'exécution.

Disons que vous avez ces classes sont définies:

// in assembly 1: 
public class A 
{ 
    public virtual void Foo() { } 
} 

// and in assembly 2: 

// requires explicit reference to assembly 1 to use 
public class B : A 
{ 
    public override void Foo() { } 
    public A Value { get; set; } 
    public void Foo(A value) { } 
} 
// has implicit reference to assembly 1, but end user can ignore 
public class C 
{ 
    private A Value { get; set; } 
    internal void Foo(A value) { } 
    protected internal A Bar() { return new A(); } 
} 
// usable at runtime even if assembly 1 is missing, as long as you don't call Foo() 
public class D 
{ 
    public void Foo() { A blah = new A(); } 
    public void Bar() { } 
} 

Si l'utilisateur final utilise la classe B, ils auront besoin d'une référence explicite à l'assemblage 1. Puisque A fait partie de l'interface publique de B, afin d'utiliser B, vous devez savoir sur A. Il existe 3 références publiques différentes à A, et l'une d'entre elles nécessitera connaître A pour utiliser B.

Cependant, la classe C fait référence à A, mais toutes les références sont privées/interne/local. Puisque toute référence à A est cachée de l'extérieur, l'utilisateur final n'a pas besoin de connaître explicitement l'assemblage 1. Il sera toujours requis lors de l'exécution, mais vous n'avez pas besoin de l'ajouter comme référence, c'est une référence indirecte .

Et si l'utilisateur final utilise la classe D, sans jamais utiliser B ou C, l'assembly 1 ne sera chargé que si vous appelez D.Foo(), qui a une variable locale de type A. Vous pouvez réellement utiliser D. Bar() librement même si l'assembly 1 est complètement manquant à l'exécution. Bien que si vous appelez D.Foo() et assembly 1 est manquant, vous obtiendrez une exception.

+0

Je comprends. Dans mon cas, je ne peux pas m'en éloigner puisque j'en héritais directement (scénario 1). Cependant, la réponse que je cherchais à ce moment-là était ILMerge (que je n'avais pas à l'époque bien sûr mais que j'ai découvert plus tard)! – Mrchief

+0

Grande explication de la façon dont cela fonctionne, mais je voudrais comprendre pourquoi ils l'ont conçu de cette façon. Lorsque vous faites une construction, Assembly1.dll aller dans le dossier bin de toute façon, alors pourquoi avoir besoin d'une référence explicite? – Borek

+0

C'est probablement pour faciliter le travail du compilateur. De cette façon, il peut dire que "ce type requiert une référence explicite à un autre assembly" ou "ce type ne comprend que des références internes à un autre assembly", sans avoir à analyser comment chaque membre de la classe est utilisé. –

Questions connexes