Mam klasę o nazwie „Artykuł” w projekcie o nazwie „MyProject.Data”, która działa jako warstwa danych dla mojej aplikacji internetowej.
Mam osobny projekt o nazwie „MyProject.Admin”, który jest internetowym systemem administracyjnym do przeglądania / edycji danych i został zbudowany przy użyciu ASP.NET Dynamic Data.
Zasadniczo chcę rozszerzyć klasę Article, używając klasy częściowej, aby móc rozszerzyć jedną z jej właściwości o rozszerzenie „UIHint”, które pozwoli mi zastąpić zwykłe wielowierszowe pole tekstowe kontrolką FCKEdit.
Moja klasa częściowa i ekstender wyglądałyby tak:
[MetadataType(typeof(ProjectMetaData))]
public partial class Project
{
}
public class ProjectMetaData
{
[UIHint("FCKeditor")]
public object ItemDetails { get; set; }
}
Teraz wszystko działa dobrze, jeśli klasa częściowa znajduje się w tym samym projekcie co oryginalna klasa częściowa - tj. Projekt MyProject.Data.
Jednak zachowanie interfejsu użytkownika nie powinno znajdować się w warstwie danych, ale raczej w warstwie administracyjnej. Dlatego chcę przenieść tę klasę do MyProject.Admin.
Jeśli jednak to zrobię, utracę funkcjonalność.
Moje podstawowe pytanie brzmi: czy mogę mieć 2 klasy cząstkowe w oddzielnych projektach, ale obie odnoszące się do tej samej „klasy”?
Jeśli nie, czy istnieje sposób, aby osiągnąć to, co próbuję zrobić, bez mieszania logiki warstwy danych z logiką interfejsu użytkownika?
źródło
MetadataType
sprawia, że modele bardziej przypominają ViewModels.Odpowiedzi:
Nie, nie można mieć dwóch klas częściowych odwołujących się do tej samej klasy w dwóch różnych zespołach (projektach). Po skompilowaniu zestawu metadane są zapisywane, a Twoje klasy nie są już częściowe. Klasy częściowe umożliwiają podzielenie definicji tej samej klasy na dwa pliki.
źródło
Jak już wspomniano, klasy częściowe są zjawiskiem czasu kompilacji, a nie środowiska wykonawczego. Klasy w zespołach są z definicji kompletne.
W terminologii MVC chcesz, aby kod widoku był oddzielony od kodu modelu, ale włączał określone rodzaje interfejsu użytkownika na podstawie właściwości modelu. Sprawdź doskonały przegląd różnych smaków MVC, MVP i tak dalej Martina Fowlera : znajdziesz mnóstwo pomysłów na projekt. Przypuszczam, że można również użyć funkcji Dependency Injection, aby powiedzieć interfejsowi użytkownika, jakiego rodzaju kontrolki są wykonalne dla poszczególnych jednostek i atrybutów.
Twój cel oddzielenia obaw jest świetny; ale klasy częściowe były przeznaczone do rozwiązywania zupełnie innych problemów (głównie z generowaniem kodu i językami modelowania w czasie projektowania).
źródło
Metody rozszerzeń i modele widoków są standardowym sposobem rozszerzania obiektów warstwy danych w interfejsie użytkownika w następujący sposób:
Warstwa danych (biblioteka klas, Person.cs):
namespace MyProject.Data.BusinessObjects { public class Person { public string Name {get; set;} public string Surname {get; set;} public string Details {get; set;} } }
Warstwa wyświetlania (aplikacja internetowa) 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 (dla rozszerzonych danych specyficznych dla widoku):
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;} } } }
Kontroler PersonController.cs:
public ActionMethod Person(int id) { var model = new PersonViewModel(); model.Data = MyDataProvider.GetPersonById(id); model.MetaData = MyDataProvider.GetPersonMetaData(id); return View(model); }
Widok, 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)
źródło
Dodaj plik podstawowy jako plik połączony do swoich projektów. Jest to nadal częściowe, ale pozwala na udostępnianie go między obydwoma projektami, utrzymywanie ich zsynchronizowania i jednocześnie posiadanie kodu specyficznego dla wersji / platformy w klasach częściowych.
źródło
Miałem z tym podobne problemy. Zachowałem klasy częściowe w moim projekcie Data, czyli w twoim przypadku „MyProject.Data”. MetaDataClasses nie powinny trafiać do projektu administratora, ponieważ w inny sposób utworzysz cykliczne odwołania.
Dodałem nowy projekt Class Lib dla moich MetaDataClasses, np. „MyProject.MetaData”, a następnie odwołałem się do tego z mojego projektu Data
źródło
Być może użyj statycznej klasy rozszerzenia.
źródło
Po prostu dodaj plik klasy jako łącze w nowym projekcie i zachowaj tę samą przestrzeń nazw w klasie częściowej.
źródło
Mogę się mylić, ale czy nie mógłbyś po prostu zdefiniować klasy ProjectMetaData w swoim projekcie MyProject.Admin?
źródło
Od 2019 możesz mieć 2 części częściowej klasy w różnych zespołach za pomocą sztuczki. Ta sztuczka została wyjaśniona i zademonstrowana w tym artykule:
https://www.notion.so/vapolia/Secret-feature-Xamarin-Forms-control-s-auto-registration-1fd6f1b0d98d4aabb2defa0eb14961fa
Wykorzystuje w swej istocie rozszerzenie MSBuild.Sdk.Extras do projektów podobnych do SDK, które rozwiązuje ograniczenia związane z posiadaniem wszystkich częściowych części klasy w tym samym zestawie, używając jednego projektu z wieloma jednoczesnymi celami, skutecznie tworząc zestawy wielokrotne w jednej kompilacji tego samego projektu.
źródło