異なるアセンブリの2つの部分クラスが同じクラスを表すことは可能ですか?


128

'MyProject.Data'というプロジェクトに 'Article'というクラスがあります。これは、私のWebアプリケーションのデータレイヤーとして機能します。

'MyProject.Admin'という別のプロジェクトがあります。これは、データを表示/編集するためのWebベースの管理システムであり、ASP.NET動的データを使用してビルドされました。

基本的に、部分クラスを使用してArticleクラスを拡張し、そのプロパティの1つを「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を構築しようとしており、データクラスにビューと検証ロジックが必要です。ばかげた。これらの属性を適用するより良い方法があるはずです。Fluent APIなどを使用して、メタデータクラスをデータクラスに関連付けることができるはずです。それはで焼かれるべきではありません。
ジム

他のいくつかの回答はこれについて言及しています:それが絶対必要であり、参照されたアセンブリソースを所有している場合、ソースモデルをリンクファイル(Add-Existing-Itemファイルピッカーの分割ボタン)として常に含めることができるため、アセンブリ参照の代わりに消費します。(Service Referenceを使用してWCF経由でモデル/データレイヤーを公開し、それらの部分的なコード生成クラスを拡張するのと同様の方法です。)レイヤーをスマッシュする必要はありません。いつでもサブクラス化できます。そしてMetadataType、ModelsをViewModelsのようにします。
JoeBrockhaus

応答するには遅すぎますが、ここで
Usman

私は手遅れになるのを知っていますが、ここで解決策を提示しました。
ウスマン、2016年

回答:


178

いいえ、2つの異なるアセンブリ(プロジェクト)で同じクラスを参照する2つの部分クラスを持つことはできません。アセンブリがコンパイルされると、メタデータが組み込まれ、クラスは部分的ではなくなります。部分クラスを使用すると、同じクラスの定義を2つのファイルに分割できます。


15

前述のように、部分クラスはコンパイル時の現象であり、ランタイムではありません。アセンブリ内のクラスは、定義により完全です。

MVCの用語では、ビューコードをモデルコードから分離したまま、モデルプロパティに基づいて特定の種類のUIを有効にします。Martin Fowlerによる、MVC、MVPのさまざまなフレーバーの優れた概要などをチェックしてください。デザインのアイデアはたくさんあります。Dependency Injectionを使用して、個々のエンティティと属性で実行可能なコントロールの種類をUIに通知することもできると思います。

懸念を分離するというあなたの目的は素晴らしいです。ただし、部分クラスは完全に異なる問題(主にコード生成と設計時モデリング言語)に対処することを目的としていました。


8

拡張メソッドとViewModelは、次のようにフロントエンドでデータレイヤーオブジェクトを拡張する標準的な方法です。

データレイヤー(クラスライブラリ、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;} }
  }
}

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

Extensionsコメントはかなり意味があります。これは、インターフェイスを使用してPersonオブジェクトから完全に切り離すことができます。私はそれが好きです!
Pale Ale

2

ベースファイルをリンクファイルとしてプロジェクトに追加します。それはまだ部分的ですが、両方のプロジェクト間で共有できるように、それらを同期させておくと同時に、部分クラスにバージョン/フレームワーク固有のコードを含めます。


1

これに関しても同様の問題がありました。私は自分の部分クラスをDataプロジェクトに保持したので、あなたの場合は 'MyProject.Data'にしました。MetaDataClassesは、別の方法で循環参照を作成するため、管理プロジェクトに含めないでください。

MetaDataClassesに新しいクラスライブラリプロジェクト(例: 'MyProject.MetaData')を追加し、これを私のDataプロジェクトから参照しました



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のようなプロジェクトに使用します。これにより、1つのプロジェクトで複数の同時ターゲットを使用し、1つのコンパイルで複数のアセンブリを効率的に作成することにより、クラスのすべての部分が同じアセンブリにあるという制限が解決されます。同じプロジェクトの。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.