Có thể có hai lớp một phần trong các hội đồng khác nhau đại diện cho cùng một lớp?


128

Tôi có một lớp gọi là 'Bài viết' trong một dự án có tên 'MyProject.Data', hoạt động như lớp dữ liệu cho ứng dụng web của tôi.

Tôi có một dự án riêng gọi là 'MyProject.Admin', đây là một hệ thống quản trị dựa trên web để xem / chỉnh sửa dữ liệu và được xây dựng bằng ASP.NET Dynamic Data.

Về cơ bản tôi muốn mở rộng lớp Article, sử dụng lớp một phần, để tôi có thể gia tăng một trong các thuộc tính của nó bằng bộ mở rộng "UIHint", cho phép tôi thay thế hộp văn bản nhiều dòng thông thường bằng điều khiển FCKEdit.

Lớp một phần và bộ mở rộng của tôi sẽ trông như thế này:

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

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

Bây giờ tất cả đều hoạt động tốt nếu lớp một phần nằm trong cùng dự án với lớp một phần gốc - tức là dự án MyProject.Data.

Nhưng hành vi UI không nên ngồi trong lớp Dữ liệu, mà thay vào đó, trong lớp Quản trị viên. Vì vậy, tôi muốn chuyển lớp này sang MyProject.Admin.

Tuy nhiên, nếu tôi làm điều đó, chức năng sẽ bị mất.

Câu hỏi cơ bản của tôi là: tôi có thể có 2 lớp một phần trong các dự án riêng biệt, nhưng cả hai đều đề cập đến cùng một "lớp" không?

Nếu không, có cách nào để thực hiện những gì tôi đang cố gắng thực hiện mà không trộn lẫn logic lớp dữ liệu với logic UI không?


1
Đây chính xác là lý do tại sao khái niệm MetadataType bốc mùi. ( vi.wikipedia.org/wiki/Code_smell ). Đó là một giải pháp hoàn toàn thiếu sót - Bạn đang cố gắng xây dựng MVC tách biệt mô hình khỏi chế độ xem khỏi bộ điều khiển và bạn cần xem logic và xác thực logic trong các lớp dữ liệu. Vô lý. Cần có một cách tốt hơn để áp dụng các thuộc tính này. Bạn sẽ có thể liên kết một lớp siêu dữ liệu với một lớp dữ liệu bằng cách sử dụng API trôi chảy hoặc một cái gì đó tương tự. Nó không nên được nướng trong.
Jim

Một số câu trả lời khác đề cập đến điều này: Nếu đó là điều bắt buộc tuyệt đối và bạn sở hữu nguồn lắp ráp được tham chiếu, bạn luôn có thể bao gồm các mô hình nguồn dưới dạng tệp được liên kết (nút tách trên trình chọn tệp Thêm mục hiện có) để chúng được xây dựng với tiêu thụ thay vì lắp ráp ref. (Chiến lược tương tự để hiển thị lớp Mô hình / Dữ liệu của bạn thông qua WCF với Tham chiếu dịch vụ và mở rộng các lớp được mã hóa một phần đó.) Bạn không bao giờ bị buộc phải đập vỡ các lớp - bạn luôn có thể phân lớp. Và MetadataTypelàm cho các mô hình giống như ViewModels hơn.
JoeBrockhaus

Quá muộn để trả lời, nhưng tôi đã cung cấp một giải pháp Tại đây
Usman

Tôi biết đã quá muộn để trả lời, nhưng ở đây tôi đã trình bày một giải pháp.
Usman

Câu trả lời:


178

Không, bạn không thể có hai lớp một phần tham chiếu đến cùng một lớp trong hai cụm (dự án) khác nhau. Sau khi tập hợp được biên dịch, siêu dữ liệu được đưa vào và các lớp của bạn không còn là một phần nữa. Các lớp một phần cho phép bạn chia định nghĩa của cùng một lớp thành hai tệp.


15

Như đã lưu ý, các lớp một phần là một hiện tượng thời gian biên dịch, không phải thời gian chạy. Các lớp trong hội đồng được định nghĩa hoàn thành.

Trong thuật ngữ MVC, bạn muốn giữ mã xem tách biệt với mã mô hình, nhưng vẫn cho phép một số loại UI nhất định dựa trên các thuộc tính mô hình. Kiểm tra tổng quan tuyệt vời của Martin Fowler về các hương vị khác nhau của MVC, MVP và không có gì: bạn sẽ tìm thấy nhiều ý tưởng thiết kế. Tôi cho rằng bạn cũng có thể sử dụng Dependency Injection để cho UI biết loại điều khiển nào khả thi đối với các thực thể và thuộc tính riêng lẻ.

Mục đích của bạn để phân tách mối quan tâm là rất lớn; nhưng các lớp một phần được dự định để giải quyết các vấn đề hoàn toàn khác nhau (chủ yếu là với các ngôn ngữ mô hình hóa thời gian thiết kế và tạo mã).


8

Các phương thức mở rộng và ViewModels là cách tiêu chuẩn để mở rộng các đối tượng lớp dữ liệu trong frontend như thế này:

Lớp dữ liệu (thư viện lớp, Person.cs):

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

Lớp hiển thị (ứng dụng 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 (đối với dữ liệu cụ thể của chế độ xem mở rộng):

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

Bộ điều khiển PersonControll.cs:

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

  return View(model);
}

Xem, 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)

Nhận xét Tiện ích mở rộng có ý nghĩa khá lớn, điều này có thể được tách rời hoàn toàn khỏi đối tượng Person bằng cách sử dụng giao diện. Tôi thích nó!
Pale Ale

2

Thêm tệp cơ sở dưới dạng tệp được liên kết vào các dự án của bạn. Nó vẫn là một phần nhưng như cho phép bạn chia sẻ nó giữa cả hai dự án, giữ cho chúng được đồng bộ hóa và đồng thời có mã cụ thể của phiên bản / khung trong các lớp một phần.


1

Tôi đã có vấn đề tương tự với điều này. Tôi đã giữ các lớp một phần của mình trong dự án Dữ liệu của mình để trong trường hợp của bạn là 'MyProject.Data'. MetaDataC Cầu không nên đi trong dự án Quản trị viên của bạn vì bạn sẽ tạo một tài liệu tham khảo vòng tròn khác.

Tôi đã thêm một dự án Class Lib mới cho MetaDataC Cầu của tôi, ví dụ 'MyProject.MetaData' và sau đó tham chiếu dự án này từ dự án Dữ liệu của tôi


1

Có lẽ sử dụng một lớp mở rộng tĩnh.


Ý tưởng tốt. Bạn có thể cung cấp một ví dụ về những gì bạn nghĩ sẽ cung cấp đủ chức năng trong câu trả lời của bạn?
pvanhouten

0

Tôi có thể bị nhầm ở đây, nhưng bạn có thể không chỉ định nghĩa lớp ProjectMetaData trong dự án MyProject.Admin của bạn không?


0

Chỉ cần thêm tệp lớp làm liên kết trong dự án mới của bạn và giữ cùng một không gian tên trong lớp một phần của bạn.


0

Kể từ năm 2019, bạn có thể có 2 phần của một lớp một phần trong các hội đồng khác nhau bằng một thủ thuật. Thủ thuật này được giải thích và thể hiện trong bài viết này:

https://www.notion.so/vapolia/Secret-feature-Xamarin-Forms-control-s-auto-registration-1fd6f1b0d98d4aabb2defa0eb14961fa

Nó sử dụng phần mở rộng của MSBuild.Sdk.Extras cho SDK giống như các dự án, giải quyết giới hạn của việc có tất cả các phần của một lớp trong cùng một tổ hợp, bằng cách sử dụng một dự án với nhiều mục tiêu đồng thời, tạo ra nhiều tập hợp trong một phần tổng hợp của cùng một dự án.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.