MonoState,Singleton或Derived Forms:CRUD应用程序的最佳方法?

时间:2021-07-02 15:49:07

I have a fairly large CRUD WinForm app that has numerous objects. Person, Enrollment, Plan, CaseNote etc. There are over 30 forms that make up the app with the UI broken down logically. Member, Enrollments, Plans, CaseNotes, etc.

我有一个相当大的CRUD WinForm应用程序,有很多对象。人员,注册,计划,案例注释等。有超过30个表单构成了应用程序,UI在逻辑上被细分。会员,报名,计划,CaseNotes等

I am trying to figure out how I can create my Person Object after searching on the Search Form and pass THE object to the next requested form. Whatever that may be, let's say Demographics. The short of it is that I need the Person object to be available throughout the App and there can only be one.

我试图找出如何在搜索表单上搜索并将该对象传递给下一个请求的表单后如何创建我的Person对象。无论那是什么,让我们说人口统计学。缺点是我需要Person对象在整个App中可用,并且只能有一个。

Now I have ZERO exposure to Design Patterns but I am trying. I have read http://www.switchonthecode.com/tutorials/csharp-tutorial-singleton-pattern and http://www.yoda.arachsys.com/csharp/singleton.html but I want to make sure I understand correctly how to apply this to my situation.

现在我有ZERO接触设计模式,但我正在尝试。我已阅读http://www.switchonthecode.com/tutorials/csharp-tutorial-singleton-pattern和http://www.yoda.arachsys.com/csharp/singleton.html但我想确保我正确理解将此应用于我的情况。

First, the examples state that you are accessing a reference, correct? Am I mistaken or would I need to access the value?

首先,示例说明您正在访问引用,对吗?我错了还是需要访问该值?

Second, is there anything else that I need to do to make this Globally available? Do I just declare a instance on each form but through this Singleton Pattern so as to not have more then one?

其次,还有什么我需要做的才能使全球可用吗?我只是在每个表单上声明一个实例,但通过这个Singleton模式,以便没有多于一个吗?

Thanks

EDIT 1

To clarify, All objects are child objects of Person. Also, As the Search Page eludes to; the users can select a different currentPerson. But they can only interact with ONE Person at a time.

为了澄清,所有对象都是Person的子对象。此外,正如搜索页面所躲避的那样;用户可以选择不同的currentPerson。但他们一次只能与一个人互动。

Lastly, as I stated I am an infant in this and if I should be considering something else, a different approach please say so and if you'd be so kind as to offer some explanation as to why, I'd be very grateful.

最后,正如我所说的那样,我是一个婴儿,如果我应该考虑其他事情,请说明一个不同的方法,如果你愿意提供一些解释,为什么,我会非常感激。

EDIT 2

Based on Medicine Man's comment I thought I wauld clarify.

根据Medicine Man的评论我认为我已经澄清了。

First, Thank you to everyone who has contributed so far. Second, I don't know the first thing about design patterns and I certainly don't have the foggiest if a certain one is needed in my current situation.

首先,感谢迄今为止贡献的所有人。其次,我不知道关于设计模式的第一件事,如果在我目前的情况下需要某一个,我肯定没有最模糊的。

If someone has a better, simpler, or ,in your opinion, a more fitting method of passing a Data Object from FORM to FORM to FORM then PLEASE tell.

如果有人有一个更好,更简单,或者,在您看来,更合适的方法将数据对象从FORM传递到FORM到FORM然后请告诉。

In the end I just need a way of tracking the information as my users go from place to place. Thank You

最后,我需要一种跟踪信息的方法,因为我的用户从一个地方到另一个地方。谢谢


5 个解决方案

#1


You can use the Singleton pattern to assure that only one instance is ever created.

您可以使用Singleton模式确保只创建一个实例。

However, the jury is still out (at least in my mind) on whether this is a good decision. There's plenty of reading on SO and other places about this.

然而,陪审团仍然(至少在我看来)是否这是一个好的决定。 SO和其他地方有关于此的大量阅读。

I would approach this from a different angle. I'd make all of my forms take in a Person instance in the constructor. That way, each form is only ever worried about it's instance of Person.

我会从不同的角度来看待这个问题。我将所有表单都放在构造函数中的Person实例中。这样,每个表单只会担心它的Person实例。

You could do this by creating a new class that inherits from Form and has a field/property/constructor for your Person. Then, any form that uses Person can inherit from your new class.

您可以通过创建一个继承自Form的新类来实现此目的,并为您的Person提供字段/属性/构造函数。然后,任何使用Person的表单都可以从您的新类继承。

You would, of course, have to manage the creation of your Person object. You could even do this with a singleton. However, the benefit is that each form doesn't have to know how to create a Person or who created the Person. That way, if you choose to move away from the Singleton pattern, you wouldn't have to go change all of your references to your singleton instance.

当然,您必须管理Person对象的创建。你甚至可以用单身人士做到这一点。但是,好处是每个表单不必知道如何创建Person或创建Person的人。这样,如果您选择远离Singleton模式,则不必更改对单例实例的所有引用。

EDIT:

Here's some code to demonstrate this. It took me a while to get the designer to play nice. I had to add an empty private constructor in PersonForm to get the designer to not throw an error.

这里有一些代码来演示这一点。我花了一段时间才让设计师玩得很开心。我必须在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 (add a label named label1)

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

#2


First, the examples state that you are accessing a reference, correct? Am I mistaken or would I need to access the value?

首先,示例说明您正在访问引用,对吗?我错了还是需要访问该值?

Your class that you are accessing is a reference to a single class in memory. For example, say your class is:

您正在访问的类是对内存中单个类的引用。例如,说你的班级是:

public class Person { ... }

If you have a singleton of that, you'll have a single "Person" saved in memory, with a shared reference to that one person in the singleton. When you access your single person, you'll be working with that reference, which is probably what you want. Any changes to the person will change it everywhere.

如果你有一个单身,你将在内存中保存一个“人”,并在单身人士*享一个人。当您访问单个人时,您将使用该引用,这可能是您想要的。对此人的任何更改都会在任何地方改变它。

Second, is there anything else that I need to do to make this Globally available? Do I just declare a instance on each form but through this Singleton Pattern so as to not have more then one?

其次,还有什么我需要做的才能使全球可用吗?我只是在每个表单上声明一个实例,但通过这个Singleton模式,以便没有多于一个吗?

Singletons are used to basically enforce that every time you use the object, it's the same object (each use is a separate reference to the one, single object in memory). You can just grab the singleton anywhere you need it, and it'll just work.

单例用于基本上强制执行每次使用对象时,它都是相同的对象(每次使用都是对内存中单个对象的单独引用)。你可以在你需要的任何地方抓住单身人士,它就会起作用。

#3


You could do something like this:

你可以这样做:

public static class PersonController
{
    private static Person _Person;

    public static Person GetPerson()
    {
        if (_Person == null)
            _Person = new Person();

        return _Person;
    }
}

This will ensure there is only one person object. You will be getting a reference to the _Person object, not a copy, so any changes will be to the single object you're expecting.

这将确保只有一个人对象。您将获得对_Person对象的引用,而不是副本,因此任何更改都将是您期望的单个对象。

#4


As Reed says, singletons enforce that the same object is used throughout the application. However, from your question it doesn't look to me like you do have the same instance of the person class available throughout the entire application, since there is the "search form" which looks like it allows you to change the currently selected person.

正如里德所说,单身人士强制要求在整个应用程序中使用相同的对象。但是,从您的问题来看,它并不像我在整个应用程序中拥有相同的人员类实例,因为有“搜索表单”,它可以让您更改当前选定的人员。

In this case your singleton may need to be a container class that holds the current context of the application and which person is currently selected. This may be something like:

在这种情况下,您的单例可能需要是一个容器类,它包含应用程序的当前上下文以及当前选择的人员。这可能是这样的:

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() { }
}

(Note that this isn't an ideal singleton pattern since it isn't thread safe...)

(请注意,这不是一个理想的单例模式,因为它不是线程安全的......)

Then the search form would set the currently selected person with:

然后搜索表单将设置当前选定的人:

Context.Instance.CurrentlySelectedPerson = personSelectedInForm;

And the demographic from can use it like:

人口统计可以使用它像:

//Get the demographics for the current person
ShowDemographics(Context.Instance.CurrentlySelectedPerson);

#5


You could also use the monostate pattern with your Personclass.

您也可以在Personclass中使用monostate模式。

public class Person
{
    public Guid Id { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }
}

Build a monostate object for Person.

为Person构建一个monostate对象。

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

Now you can initialize the monostate.

现在您可以初始化单稳态。

CurrentPerson.Person = GetPersonByUserInput();

And then use CurrentPerson instances throughout the code and they will all access a common shared state.

然后在整个代码中使用CurrentPerson实例,它们都将访问公共共享状态。

CurrentPerson currentPerson = new CurrentPerson();

#1


You can use the Singleton pattern to assure that only one instance is ever created.

您可以使用Singleton模式确保只创建一个实例。

However, the jury is still out (at least in my mind) on whether this is a good decision. There's plenty of reading on SO and other places about this.

然而,陪审团仍然(至少在我看来)是否这是一个好的决定。 SO和其他地方有关于此的大量阅读。

I would approach this from a different angle. I'd make all of my forms take in a Person instance in the constructor. That way, each form is only ever worried about it's instance of Person.

我会从不同的角度来看待这个问题。我将所有表单都放在构造函数中的Person实例中。这样,每个表单只会担心它的Person实例。

You could do this by creating a new class that inherits from Form and has a field/property/constructor for your Person. Then, any form that uses Person can inherit from your new class.

您可以通过创建一个继承自Form的新类来实现此目的,并为您的Person提供字段/属性/构造函数。然后,任何使用Person的表单都可以从您的新类继承。

You would, of course, have to manage the creation of your Person object. You could even do this with a singleton. However, the benefit is that each form doesn't have to know how to create a Person or who created the Person. That way, if you choose to move away from the Singleton pattern, you wouldn't have to go change all of your references to your singleton instance.

当然,您必须管理Person对象的创建。你甚至可以用单身人士做到这一点。但是,好处是每个表单不必知道如何创建Person或创建Person的人。这样,如果您选择远离Singleton模式,则不必更改对单例实例的所有引用。

EDIT:

Here's some code to demonstrate this. It took me a while to get the designer to play nice. I had to add an empty private constructor in PersonForm to get the designer to not throw an error.

这里有一些代码来演示这一点。我花了一段时间才让设计师玩得很开心。我必须在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 (add a label named label1)

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

#2


First, the examples state that you are accessing a reference, correct? Am I mistaken or would I need to access the value?

首先,示例说明您正在访问引用,对吗?我错了还是需要访问该值?

Your class that you are accessing is a reference to a single class in memory. For example, say your class is:

您正在访问的类是对内存中单个类的引用。例如,说你的班级是:

public class Person { ... }

If you have a singleton of that, you'll have a single "Person" saved in memory, with a shared reference to that one person in the singleton. When you access your single person, you'll be working with that reference, which is probably what you want. Any changes to the person will change it everywhere.

如果你有一个单身,你将在内存中保存一个“人”,并在单身人士*享一个人。当您访问单个人时,您将使用该引用,这可能是您想要的。对此人的任何更改都会在任何地方改变它。

Second, is there anything else that I need to do to make this Globally available? Do I just declare a instance on each form but through this Singleton Pattern so as to not have more then one?

其次,还有什么我需要做的才能使全球可用吗?我只是在每个表单上声明一个实例,但通过这个Singleton模式,以便没有多于一个吗?

Singletons are used to basically enforce that every time you use the object, it's the same object (each use is a separate reference to the one, single object in memory). You can just grab the singleton anywhere you need it, and it'll just work.

单例用于基本上强制执行每次使用对象时,它都是相同的对象(每次使用都是对内存中单个对象的单独引用)。你可以在你需要的任何地方抓住单身人士,它就会起作用。

#3


You could do something like this:

你可以这样做:

public static class PersonController
{
    private static Person _Person;

    public static Person GetPerson()
    {
        if (_Person == null)
            _Person = new Person();

        return _Person;
    }
}

This will ensure there is only one person object. You will be getting a reference to the _Person object, not a copy, so any changes will be to the single object you're expecting.

这将确保只有一个人对象。您将获得对_Person对象的引用,而不是副本,因此任何更改都将是您期望的单个对象。

#4


As Reed says, singletons enforce that the same object is used throughout the application. However, from your question it doesn't look to me like you do have the same instance of the person class available throughout the entire application, since there is the "search form" which looks like it allows you to change the currently selected person.

正如里德所说,单身人士强制要求在整个应用程序中使用相同的对象。但是,从您的问题来看,它并不像我在整个应用程序中拥有相同的人员类实例,因为有“搜索表单”,它可以让您更改当前选定的人员。

In this case your singleton may need to be a container class that holds the current context of the application and which person is currently selected. This may be something like:

在这种情况下,您的单例可能需要是一个容器类,它包含应用程序的当前上下文以及当前选择的人员。这可能是这样的:

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() { }
}

(Note that this isn't an ideal singleton pattern since it isn't thread safe...)

(请注意,这不是一个理想的单例模式,因为它不是线程安全的......)

Then the search form would set the currently selected person with:

然后搜索表单将设置当前选定的人:

Context.Instance.CurrentlySelectedPerson = personSelectedInForm;

And the demographic from can use it like:

人口统计可以使用它像:

//Get the demographics for the current person
ShowDemographics(Context.Instance.CurrentlySelectedPerson);

#5


You could also use the monostate pattern with your Personclass.

您也可以在Personclass中使用monostate模式。

public class Person
{
    public Guid Id { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }
}

Build a monostate object for Person.

为Person构建一个monostate对象。

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

Now you can initialize the monostate.

现在您可以初始化单稳态。

CurrentPerson.Person = GetPersonByUserInput();

And then use CurrentPerson instances throughout the code and they will all access a common shared state.

然后在整个代码中使用CurrentPerson实例,它们都将访问公共共享状态。

CurrentPerson currentPerson = new CurrentPerson();