Возможно ли, чтобы два отдельных класса в разных сборках представляли один и тот же класс?

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

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

В принципе, я хочу расширить класс 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 частичных класса в отдельных проектах, но оба относятся к одному и тому же "классу"?

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

Ответ 1

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

Ответ 2

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

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

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

Ответ 3

Методы расширения и 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;} }
  }
}

Контроллер 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/[email protected](Model.MetaData["image"]).png" >
<ul>
  <li>@Model.MetaData["comments"]</li>
  <li>@Model.MetaData["employer_comments"]</li>
</ul>
@Html.EditorFor(m => m.PersonDetails)

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

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

Ответ 8

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