Est-il possible d'avoir deux classes partielles dans des assemblages différents représentant la même classe?

J'ai une classe appelée "Article" dans un projet appelé " MyProject.Data', qui agit comme couche de données pour mon application web.

J'ai un projet séparé appelé ' MyProject.Admin', qui est un système d'administration basé sur le web pour afficher / modifier les données, et a été construit en utilisant ASP.NET données dynamiques.

Fondamentalement, je veux étendre la classe Article, en utilisant une classe partielle, afin que je puisse augmenter l'une de ses propriétés avec un extender "UIHint" , ce qui me permettra de remplacer la normale zone de texte multi-ligne avec un contrôle FCKEdit.

Ma classe partielle et l'extension ressembleraient à ceci:

[MetadataType(typeof(ProjectMetaData))]
public partial class Project
{
}

public class ProjectMetaData
{
    [UIHint("FCKeditor")]
    public object ItemDetails { get; set; }
}

Maintenant, tout fonctionne bien si la classe partielle est dans le même projet que la classe partielle d'origine - c'est-à-dire le MyProject.Les données de projet.

Mais le comportement de L'interface utilisateur ne doit pas rester dans la couche de données, mais plutôt dans la couche Admin. Donc, je veux déplacer cette classe vers MyProject.Admin.

Cependant, si je fais cela, la fonctionnalité est perdue.

Ma question fondamentale est: puis-je avoir 2 classes partielles dans des projets séparés, mais les deux se référant à la même "classe"?

Sinon, existe-t-il un moyen d'accomplir ce que j'essaie de faire, sans mélanger la logique de la couche de données avec la logique de L'interface utilisateur?

117
demandé sur Marius Schulz 2009-03-15 09:25:46

8 réponses

Non, vous ne pouvez pas avoir deux classes partielles se référant à la même classe dans deux assemblages différents (projets). Une fois l'assembly compilé, les méta-données sont intégrées et vos classes ne sont plus partielles. Classes partielles permet de diviser la définition de la même classe en deux fichiers.

162
répondu Darin Dimitrov 2015-09-29 09:15:57

Comme indiqué, les classes partielles sont un phénomène de compilation, pas d'exécution. Les Classes dans les assemblages sont par définition complètes.

En termes MVC, vous voulez garder le code de vue séparé du code de modèle, tout en activant certains types d'interface utilisateur en fonction des propriétés du modèle. Découvrez L'excellent aperçu de Martin Fowler des différentes saveurs de MVC, MVP et autres: vous trouverez des idées de design à profusion. Je suppose que vous pouvez également utiliser Dependency Injection pour dire à L'interface utilisateur quel type de les contrôles sont viables pour les entités et les attributs.

Votre objectif de séparer les préoccupations est grand; mais les classes partielles étaient destinées à résoudre des problèmes entièrement différents (principalement avec la génération de code et les langages de modélisation en temps de conception).

12
répondu Pontus Gagge 2009-03-15 08:46:50

Les méthodes D'Extension et ViewModels sont le moyen standard d'étendre les objets de couche de données dans le frontend comme ceci:

Couche de données (bibliothèque de classes, personne.cs):

namespace MyProject.Data.BusinessObjects
{
  public class Person
  {
    public string Name {get; set;}
    public string Surname {get; set;}
    public string Details {get; set;}
  }
}

Couche D'affichage (application web) PersonExtensions.cs:

using Data.BusinessObjects
namespace MyProject.Admin.Extensions
{
  public static class PersonExtensions
  {
    public static HtmlString GetFormattedName(this Person person)
    {
       return new HtmlString(person.Name + " <b>" + person.Surname</b>);
    }
  }
}

ViewModel (pour les données spécifiques à une vue étendue):

using Data.BusinessObjects
namespace MyProject.Admin.ViewModels
{
  public static class PersonViewModel
  {
    public Person Data {get; set;}
    public Dictionary<string,string> MetaData {get; set;}

    [UIHint("FCKeditor")]
    public object PersonDetails { get { return Data.Details; } set {Data.Details = value;} }
  }
}

Contrôleur PersonController.cs:

public ActionMethod Person(int id)
{
  var model = new PersonViewModel();
  model.Data = MyDataProvider.GetPersonById(id);
  model.MetaData = MyDataProvider.GetPersonMetaData(id);

  return View(model);
}

Vue, Personne.cshtml:

@using MyProject.Admin.Extensions

<h1>@Model.Data.GetFormattedName()</h1>
<img src="~/Images/People/image_@(Model.MetaData["image"]).png" >
<ul>
  <li>@Model.MetaData["comments"]</li>
  <li>@Model.MetaData["employer_comments"]</li>
</ul>
@Html.EditorFor(m => m.PersonDetails)
6
répondu 8DX 2013-08-01 11:31:31

Ajoutez le fichier de base en tant que fichier lié dans vos projets. C'est toujours partiel mais comme vous permet de le partager entre les deux projets, les garder synchronisés et en même temps avoir du code spécifique à la version/framework dans les classes partielles.

2
répondu leon 2011-08-24 16:40:30

J'ai eu des problèmes similaires avec cela. J'ai gardé mes classes partielles dans mon projet de données donc dans votre cas le ' MyProject.Données'. MetaDataClasses ne devrait pas aller dans votre projet Admin car vous allez créer une référence circulaire autrement.

J'ai ajouté un nouveau projet LIB de classe pour mes MetaDataClasses par exemple ' MyProject.Métadonnées ' puis référencé à partir de mon projet de données

1
répondu Indy 2011-06-24 11:18:28

Peut-être utiliser une classe d'extension statique.

1
répondu Braneloc 2012-01-11 13:43:54

Je peux me tromper ici, mais ne pourriez-vous pas simplement définir la classe ProjectMetaData dans votre MyProject.Administrateur de projet?

0
répondu Darragh 2009-11-23 13:58:58

Ajoutez simplement un fichier de classe en tant que lien dans votre nouveau projet et conservez le même espace de noms dans votre classe partielle.

0
répondu nl20121974 2012-10-29 10:15:36