MonoState、Singleton、または派生フォーム:CRUDアプリのベストアプローチ?
-
05-07-2019 - |
質問
多数のオブジェクトを持つかなり大きなCRUD WinFormアプリがあります。 個人、登録、プラン、ケースノートなど。 UIを論理的に分解して、アプリを構成する30以上のフォームがあります。 メンバー、登録、プラン、ケースノートなど。
検索フォームで検索した後、 個人オブジェクト を作成して、次のオブジェクトに渡す方法を見つけようとしています。要求されたフォーム。それが何であれ、人口統計としましょう。要するに、Personオブジェクトをアプリ全体で利用できるようにする必要があり、1つしか存在できないということです。
現在、デザインパターンをゼロに公開していますが、試しています。 http://www.switchonthecode.com/tutorials/csharp-tutorialを読みました-singleton-pattern および http://www.yoda.arachsys.com /csharp/singleton.html ですが、これを自分の状況に適用する方法を正しく理解していることを確認したいです。
まず、例では、参照にアクセスしていると述べていますが、正しいですか?間違っていますか、または value にアクセスする必要がありますか?
第二に、このグローバルに利用可能にするために私がしなければならないことは他にありますか?各フォームでインスタンスを宣言するだけですが、このシングルトンパターンを使用してインスタンスを1つだけにしてください。
ありがとう
編集1
明確にするために、すべてのオブジェクトはPersonの子オブジェクトです。また、検索ページは次のとおりです。ユーザーは別のcurrentPersonを選択できます。ただし、一度にやり取りできるのは ONE Personのみです。
最後に、私はこれについて私が幼児であると述べたので、他のことを検討する必要がある場合は、別のアプローチを言ってください、あなたが理由について説明するほど親切であれば、私はとても感謝しています。
編集2
Medicine Manのコメントに基づいて、明確にする必要があると思いました。
まず、これまで貢献してくれたすべての人に感謝します。 第二に、デザインパターンについて最初に知っていることはありませんし、特定のパターンが現在の状況で必要な場合、私は確かに最も霧がありません。
誰かがより良い、より単純な、またはあなたの意見では、フォームからフォームへデータオブジェクトを渡すより適切な方法を持っているなら、教えてください。
最終的には、ユーザーが場所を移動するときに情報を追跡する方法が必要です。 ありがとう
解決
シングルトンパターンを使用して、1つのインスタンスのみが作成されるようにすることができます。
ただし、審査員はまだ出ていない(少なくとも私の考えでは) )これが良い決定かどうかについて。これについてSOや他の場所で多くの読書があります。
別の角度からこれにアプローチします。すべてのフォームにコンストラクターのPersonインスタンスを取り込ませます。このように、各フォームはPersonのインスタンスについてのみ心配します。
これを行うには、Formを継承し、Personのフィールド/プロパティ/コンストラクターを持つ新しいクラスを作成します。その後、Personを使用するフォームは、新しいクラスから継承できます。
もちろん、Personオブジェクトの作成を管理する必要があります。これをシングルトンで行うこともできます。ただし、利点は、各フォームがPersonの作成方法やPersonの作成者を知る必要がないことです。そのようにして、シングルトンから離れることを選択した場合パターンでは、シングルトンインスタンスへのすべての参照を変更する必要はありません。
編集:
これを示すためのコードを次に示します。デザイナーに素敵なプレイをしてもらうのに少し時間がかかりました。デザイナーがエラーをスローしないようにするには、PersonFormに空のプライベートコンストラクターを追加する必要がありました。
Program.cs
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyDerivedForm(new Person { Name = "Hello World!" }));
}
}
Person.cs
public class Person
{
public virtual string Name { get; set; }
}
PersonForm.cs
using System;
using System.Windows.Forms;
public class PersonForm : Form
{
private readonly Person myPerson;
protected virtual Person MyPerson
{
get
{
return this.myPerson;
}
}
private PersonForm()
{
}
public PersonForm(Person person)
{
this.myPerson = person;
}
}
MyDerivedForm.cs(label1という名前のラベルを追加)
public partial class MyDerivedForm : SingletonMadness.PersonForm
{
public MyDerivedForm(Person person)
: base(person)
{
InitializeComponent();
}
private void MyDerivedForm_Load(object sender, EventArgs e)
{
label1.Text = this.MyPerson.Name;
}
}
他のヒント
まず、例では、参照にアクセスしていると述べていますが、正しいですか?私は間違っていますか、または値にアクセスする必要がありますか?
アクセスしているクラスは、メモリ内の単一のクラスへの参照です。たとえば、クラスは次のようになります。
public class Person { ... }
そのシングルトンがある場合は、単一の&quot; Person&quot;があります。メモリ内に保存され、シングルトン内のその1人に対する共有参照を使用します。あなたが一人の人にアクセスするとき、あなたはおそらくあなたが望むものであるその参照で作業しているでしょう。人に変更を加えると、どこでも変更されます。
第二に、これをグローバルに利用可能にするために私がしなければならないことは他にありますか?各フォームでインスタンスを宣言しますが、このシングルトンパターンを介してインスタンスを1つだけ宣言しますか?
シングルトンは基本的に、オブジェクトを使用するたびに同じオブジェクトであることを強制するために使用されます(各使用は、メモリ内の1つの単一オブジェクトへの個別の参照です)。必要な場所でシングルトンを取得するだけで機能します。
次のようなことができます:
public static class PersonController
{
private static Person _Person;
public static Person GetPerson()
{
if (_Person == null)
_Person = new Person();
return _Person;
}
}
これにより、人物オブジェクトが1つだけ存在することが保証されます。コピーではなく、_Personオブジェクトへの参照を取得するため、変更は期待する単一のオブジェクトに対して行われます。
リードが言うように、シングルトンは、アプリケーション全体で同じオブジェクトが使用されることを強制します。しかし、あなたの質問からは、「検索フォーム」があるので、アプリケーション全体で利用可能な個人クラスの同じインスタンスを持っているようには見えません。現在選択されている人を変更できるように見えます。
この場合、シングルトンはアプリケーションの現在のコンテキストを保持するコンテナクラスである必要があり、どの人が現在選択されているか 。これは次のようなものです:
public class Context
{
private static Context _instance;
public static Context Instance
{
get
{
if (_instance == null)
{
_instance = new Context();
}
return _instance;
}
}
public Person CurrentlySelectedPerson { get; set; }
private Context() { }
}
(スレッドセーフではないため、これは理想的なシングルトンパターンではないことに注意してください...)
その後、検索フォームは現在選択されている人を次のように設定します:
Context.Instance.CurrentlySelectedPerson = personSelectedInForm;
そして、人口統計は次のように使用できます:
//Get the demographics for the current person
ShowDemographics(Context.Instance.CurrentlySelectedPerson);
Person
クラスでモノステートパターンを使用することもできます。
public class Person
{
public Guid Id { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
}
Person
のモノステートオブジェクトを構築します。
public class CurrentPerson
{
public static Person Person { get; set; }
public Guid Id
{
get { return CurrentPerson.Person.Id; }
set { CurrentPerson.Person.Id = value; }
}
public String FirstName
{
get { return CurrentPerson.Person.FirstName; }
set { CurrentPerson.Person.FirstName = value; }
}
public String LastName
{
get { return CurrentPerson.Person.LastName; }
set { CurrentPerson.Person.LastName = value; }
}
}
これで、モノステートを初期化できます。
CurrentPerson.Person = GetPersonByUserInput();
そして、コード全体で CurrentPerson
インスタンスを使用すると、それらはすべて共通の共有状態にアクセスします。
CurrentPerson currentPerson = new CurrentPerson();