是否可以在不同的程序集中使两个局部类代表相同的类?


128

我在名为“ MyProject.Data”的项目中有一个名为“ Article”的类,该类充当Web应用程序的数据层。

我有一个名为“ MyProject.Admin”的单独项目,该项目是用于查看/编辑数据的基于Web的管理系统,是使用ASP.NET动态数据构建的。

基本上,我想使用部分类来扩展Article类,以便可以使用“ UIHint”扩展器来扩展其属性之一,这将允许我用FCKEdit控件替换常规的多行文本框。

我的局部类和扩展器看起来像这样:

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

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

现在,如果部分类与原始部分类在同一项目中,即MyProject.Data项目,则所有这些工作正常。

但是,UI行为不应位于数据层,而应位于管理层。因此,我想将此类移至MyProject.Admin。

但是,如果我这样做,该功能将丢失。

我的基本问题是:我可以在单独的项目中有2个局部类,但都指向同一个“类”吗?

如果没有,是否有一种方法可以完成我想做的事情,而又不会将数据层逻辑与UI逻辑混合在一起?


1
这正是MetadataType概念发臭的原因。(en.wikipedia.org/wiki/Code_smell)。这是一个完全有缺陷的解决方案-您正在尝试构建MVC,该MVC专门将模型与视图从控制器中分离出来,并且需要数据类中的视图和验证逻辑。可笑的 应该有一个更好的方法来应用这些属性。您应该能够使用流利的API或类似方法将元数据类与数据类相关联。它不应该被烤。
吉姆

其他一些答案提到了这一点:如果这是绝对必须的,并且您拥有引用的程序集源,则始终可以将源模型包括为链接文件(Add-Existing-Item文件选择器上的拆分按钮),以便使用消耗而不是装配参考。(通过WCF使用服务引用公开模型/数据层并扩展那些由部分代码生成的类的类似策略。)您从不被迫粉碎层-您始终可以子类化。而MetadataType让模型更喜欢的ViewModels。
JoeBrockhaus

现在为时已晚,但我在这里
Usman,

我知道为时已晚,但是我在这里提出了一个解决方案。
乌斯曼

Answers:


178

不可以,在两个不同的程序集(项目)中不能有两个引用同一类的局部类。一旦汇编被编译,元数据就被放入,并且您的类不再是局部的。局部类使您可以将同一类的定义分成两个文件。


15

如前所述,部分类是编译时的现象,而不是运行时的现象。根据定义,程序集中的类是完整的。

用MVC术语来说,您希望将视图代码与模型代码分开,但要基于模型属性启用某些类型的UI。查看Martin Fowler对MVC,MVP和其他各种风格的出色概述:您会发现很多设计思想。我想您也可以使用依赖注入来告诉UI哪种控件适用于单个实体和属性。

您分离关注点的目标非常好;但是部分类旨在解决完全不同的问题(主要是代码生成和设计时建模语言)。


8

扩展方法和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;}
  }
}

显示层(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(用于特定于扩展视图的数据):

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/image_@(Model.MetaData["image"]).png" >
<ul>
  <li>@Model.MetaData["comments"]</li>
  <li>@Model.MetaData["employer_comments"]</li>
</ul>
@Html.EditorFor(m => m.PersonDetails)

扩展注释很有意义,可以通过使用接口将其与Person对象完全分离。我喜欢!
苍白的啤酒

2

将基本文件作为链接文件添加到您的项目中。它仍然是局部的,但是允许您在两个项目之间共享它,使其保持同步,同时在局部类中具有特定于版本/框架的代码。


1

我也有类似的问题。我将部分类保留在Data项目中,因此在您的情况下为“ MyProject.Data”。MetaDataClasses不应进入您的Admin项目,因为您将以其他方式创建循环引用。

我为我的MetaDataClasses添加了一个新的类库项目,例如“ MyProject.MetaData”,然后从我的数据项目中引用了此项目


1

也许使用静态扩展类。


好主意。您能否提供一个示例,说明您认为可以在答案中提供足够的功能?
pvanhouten 2012年

0

我在这里可能会弄错,但是您是否不能仅在MyProject.Admin项目中定义ProjectMetaData类?


0

只需将类文件添加为新项目中的链接,并在部分类中保留相同的名称空间。


0

自2019年以来,您可以使用技巧在不同的程序集中使用局部类的2个部分。本文将说明和演示此技巧:

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

它以MSBuild.Sdk.Extras扩展为类项目的SDK的核心,通过使用一个具有多个同时目标的项目,有效地在一个编译中创建多个程序集,从而解决了将类的所有部分都放在同一程序集中的限制。同一项目的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.