Можно ли иметь два отдельных класса в разных сборках, представляющих один и тот же класс? - PullRequest
121 голосов
/ 15 марта 2009

У меня есть класс с именем Article в проекте MyProject.Data, который действует как слой данных для моего веб-приложения.

У меня есть отдельный проект под названием «MyProject.Admin», который представляет собой веб-систему администрирования для просмотра / редактирования данных и был построен с использованием ASP.NET Dynamic Data.

По сути, я хочу расширить класс Article, используя частичный класс, чтобы я мог расширить одно из его свойств с помощью расширителя "UIHint", который позволит мне заменить обычное многострочное текстовое поле элементом управления FCKEdit.

Мой частичный класс и расширитель будут выглядеть так:

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

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

Теперь все это работает нормально, если частичный класс находится в том же проекте, что и исходный частичный класс, то есть проект MyProject.Data.

Но поведение пользовательского интерфейса должно располагаться не на уровне данных, а на уровне администратора. Поэтому я хочу переместить этот класс в MyProject.Admin.

Однако, если я это сделаю, функциональность будет потеряна.

Мой фундаментальный вопрос: могу ли я иметь 2 отдельных класса в отдельных проектах, но оба ссылаются на один и тот же "класс"?

Если нет, есть ли способ выполнить то, что я пытаюсь сделать, не смешивая логику уровня данных с логикой пользовательского интерфейса?

Ответы [ 8 ]

168 голосов
/ 15 марта 2009

Нет, у вас не может быть двух частичных классов, ссылающихся на один и тот же класс в двух разных сборках (проектах). Как только сборка скомпилирована, метаданные запекаются, и ваши классы больше не являются частичными. Частичные классы позволяют разделить определение одного и того же класса на два файла.

13 голосов
/ 15 марта 2009

Как уже отмечалось, частичные классы - это феномен времени компиляции, а не времени выполнения. Классы в сборках по определению завершены.

В терминах MVC вы хотите отделить код вида от кода модели, но при этом включить определенные виды пользовательского интерфейса на основе свойств модели. Проверьте превосходный обзор Мартина Фаулера различных вариантов MVC, MVP и еще много чего: вы найдете множество дизайнерских идей. Я полагаю, вы также можете использовать Внедрение зависимостей , чтобы сообщить пользовательскому интерфейсу, какие элементы управления являются жизнеспособными для отдельных объектов и атрибутов.

Ваша цель разделения проблем велика; но частичные классы были предназначены для решения совершенно разных проблем (в первую очередь с языками генерации кода и моделирования во время разработки).

7 голосов
/ 01 августа 2013

Методы расширения и ViewModels являются стандартным способом расширения объектов уровня данных во внешнем интерфейсе следующим образом:

Уровень данных (библиотека классов, Person.cs):

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

Уровень отображения (веб-приложение) 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 (для расширенных данных, относящихся к просмотру):

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;} }
  }
}

Controller PersonController.cs:

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

  return View(model);
}

View, Person.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)
2 голосов
/ 24 августа 2011

Добавьте базовый файл как связанный файл в ваши проекты. Это все еще частично, но так как позволяет вам делиться им между обоими проектами, сохранять их синхронизированными и в то же время иметь специфичный для версии / фреймворка код в частичных классах.

1 голос
/ 11 января 2012

Возможно, использовать статический класс расширения.

1 голос
/ 24 июня 2011

У меня были похожие проблемы с этим. Я сохранил свои частичные классы в своем проекте данных, так что в вашем случае «MyProject.Data». MetaDataClasses не должны входить в ваш проект Admin, поскольку вы будете создавать циклические ссылки в других случаях.

Я добавил новый проект Class Lib для своих MetaDataClasses, например. MyProject.MetaData, а затем ссылался на это из моего проекта данных

0 голосов
/ 04 февраля 2012

Просто добавьте файл класса как ссылку в ваш новый проект и сохраните то же пространство имен в вашем частичном классе.

0 голосов
/ 23 ноября 2009

Я могу ошибаться, но не могли бы вы просто определить класс ProjectMetaData в вашем проекте MyProject.Admin?

...