2009-03-15 2 views
117

У меня есть класс под названием «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

Именно поэтому понятие MetadataType воняет. (Http://en.wikipedia.org/wiki/Code_smell). Это совершенно ошибочное решение. Вы пытаетесь создать MVC, который специально отделяет модель от представления от контроллера, и вам нужна логика просмотра и проверки в классах данных. Rediculous. Должен быть лучший способ применения этих атрибутов. Вы должны уметь сопоставлять класс метаданных с классом данных с использованием свободного API или чего-то подобного. Его не следует испечь. – Jim

+0

Некоторые другие ответы говорят об этом: если это абсолютная необходимость, и вы владеете ссылочным источником сборки, вы всегда можете включать исходные модели в качестве связанных файлов (сплит-кнопка в файле Add-Existing-Item сборщик), поэтому они построены с потреблением вместо сборки ref. (Аналогичная стратегия заключается в том, чтобы выставлять свой слой Model/Data через WCF с помощью Service Reference и расширять классы с частичным кодом.) Вы никогда не вынуждены разбивать слои - вы всегда можете подклассы. И 'MetadataType' делает модели больше похожими на ViewModels. – JoeBrockhaus

+0

Слишком поздно отвечать, но у меня есть решение [Здесь] (http://stackoverflow.com/questions/17186379/putting-dataannotation-buddy-class-in-another-assembly/37343388#37343388) – Usman

ответ

160

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

12

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

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

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

0

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

1

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

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

2

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

1

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

+0

Хорошая идея. Можете ли вы привести пример того, что, по вашему мнению, обеспечит достаточную функциональность в вашем ответе? – pvanhouten

0

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

5

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

Data Layer (библиотека классов, Person.cs):

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

Показать Layer (веб применение) 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); 
} 

вид, 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) 
Смежные вопросы