C# 如何用动作调用?

C# 如何用动作调用?,c#,winforms,invoke,C#,Winforms,Invoke,我总是将表单上的修饰符设置为private,我不喜欢内部或公共 到现在为止,我经常这样调用: public string Addtext { if(InvokeRequired) { Invoke((MethodInvoker)delegate { textbox.text = value; }); } else textbox.text = value; } 但是为

我总是将表单上的修饰符设置为private,我不喜欢内部或公共

到现在为止,我经常这样调用:

public string Addtext
{
    if(InvokeRequired)
    {
         Invoke((MethodInvoker)delegate
         {
             textbox.text = value;
         });
    }
    else
        textbox.text = value;
}
但是为表单上的每个成员添加这样的属性完全不是面向对象的

我想创建一个调用参数(操作)的函数。我尽了最大努力,但失败了-它要求表单成员必须是公共的内部的:(

public void performationform(Action)
{
var form=form.ActiveForm作为FormMain;
对象s=action.Clone();
if(form!=null)
{
形式、行为(行动);
}
}
公共无效履行(诉讼)
{
如果(需要调用)
调用(动作,这个);
其他的
行动(本);
}
我的代码中有两个问题:

它要求我要更改的属性为!=私有:(


如果窗体不在焦点上,则不起作用。

如何为需要在窗体范围之外访问或设置的数据添加属性“根本不面向对象?”这实际上是您唯一的选择。在匿名委托(或任何委托)中编写代码在声明该属性的上下文中执行。解决可见性问题的唯一工具是反射,即大的代码气味。创建属性并根据需要使用它们

至于你的第二个选项,我假设你想在你的“主窗体”上执行它。这里有两个选项:假设只有一个实例,并将其作为类的静态属性,在实例构造函数中赋值

public partial class MainForm : Form
{
    private static MainForm singletonInstance;

    public static MainForm SingletonInstance
    {
        get { return singletonInstance; }
    }

    public MainForm() : base()
    {
        InitializeComponent();

        singletonInstance = this;
    }
}

public void PerformActionOnForm(Action<FormMain> action)
{
    var form = MainForm.SingletonInstance;
    // object s = action.Clone(); What was this for?
    if (form != null)
    {
        form.PerformAction(action);
    }
}
public分部类MainForm:Form
{
私有静态主窗体;
公共静态主窗体
{
获取{return singletonistance;}
}
public MainForm():base()
{
初始化组件();
singletonistance=这个;
}
}
公共作废绩效表(行动)
{
var form=MainForm.singletonistance;
//对象s=action.Clone();这是干什么用的?
if(form!=null)
{
形式、行为(行动);
}
}
另一种方法只有在所有表单都正确“拥有”并且唯一没有所有者的表单是主表单时才有效。在这种情况下,您可以执行以下操作:

public void PerformActionOnForm(Action<FormMain> action)
{
    var form = Form.ActiveForm.TopLevelControl as FormMain;
    // object s = action.Clone(); What was this for?
    if (form != null)
    {
        form.PerformAction(action);
    }
}
public void performationform(Action)
{
var form=form.ActiveForm.TopLevelControl作为FormMain;
//对象s=action.Clone();这是干什么用的?
if(form!=null)
{
形式、行为(行动);
}
}

对于需要在表单“完全不面向对象”范围之外访问或设置的数据,如何添加属性?这实际上是您唯一的选择。在匿名委托(或任何委托)中编写代码在声明该属性的上下文中执行。解决可见性问题的唯一工具是反射,即大的代码气味。创建属性并根据需要使用它们

至于你的第二个选项,我假设你想在你的“主窗体”上执行它。这里有两个选项:假设只有一个实例,并将其作为类的静态属性,在实例构造函数中赋值

public partial class MainForm : Form
{
    private static MainForm singletonInstance;

    public static MainForm SingletonInstance
    {
        get { return singletonInstance; }
    }

    public MainForm() : base()
    {
        InitializeComponent();

        singletonInstance = this;
    }
}

public void PerformActionOnForm(Action<FormMain> action)
{
    var form = MainForm.SingletonInstance;
    // object s = action.Clone(); What was this for?
    if (form != null)
    {
        form.PerformAction(action);
    }
}
public分部类MainForm:Form
{
私有静态主窗体;
公共静态主窗体
{
获取{return singletonistance;}
}
public MainForm():base()
{
初始化组件();
singletonistance=这个;
}
}
公共作废绩效表(行动)
{
var form=MainForm.singletonistance;
//对象s=action.Clone();这是干什么用的?
if(form!=null)
{
形式、行为(行动);
}
}
另一种方法只有在所有表单都正确“拥有”并且唯一没有所有者的表单是主表单时才有效。在这种情况下,您可以执行以下操作:

public void PerformActionOnForm(Action<FormMain> action)
{
    var form = Form.ActiveForm.TopLevelControl as FormMain;
    // object s = action.Clone(); What was this for?
    if (form != null)
    {
        form.PerformAction(action);
    }
}
public void performationform(Action)
{
var form=form.ActiveForm.TopLevelControl作为FormMain;
//对象s=action.Clone();这是干什么用的?
if(form!=null)
{
形式、行为(行动);
}
}

为什么您的表单有这么多可能的入口点可以从其他线程调用?是否执行较低级别的线程封送(表单的控制器可能会有所帮助)而且您不必担心这样的样板代码。

为什么您的表单有这么多可能的入口点可以从其他线程调用?线程封送是否降低了级别(表单的控制器可能会有所帮助)您不必担心这样的样板代码。

从非UI线程调用UI组件 假设您只有一个消息循环(99%是这样),那么:

访问专用UI组件 访问私有UI成员与访问.NET对象的其他私有成员没有什么不同。这是私有成员的性质,不能从其他对象访问。如果仍要访问,则必须将UI组件的引用传递给调用方,或者使用反射来解析私有对象的路径

将UI组件的引用传递给调用方的示例:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        ThreadPool.QueueUserWorkItem(delegate { MyWorker.Run(button1); }); 
    }
}

class MyWorker
{
    public static void Run(Button button)
    {
        SynchronizedInvoker.Invoke(() => button.Text = "running");
        Thread.Sleep(5000); // do some important work here
        SynchronizedInvoker.Invoke(() => button.Text = "finished");
    }
}
从技术上讲,使用反射是可行的,但并不理想。您需要知道私有成员的路径,这需要有关对象内部的信息。然后,您应该问问自己,为什么首先将其设置为私有的。

从非UI线程调用UI组件 假设您只有一个消息循环(99%是这样),那么:

访问专用UI组件 访问私有UI成员与访问.NET对象的其他私有成员没有什么不同。它的性质是不从其他对象访问私有成员。如果
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        ThreadPool.QueueUserWorkItem(delegate { MyWorker.Run(button1); }); 
    }
}

class MyWorker
{
    public static void Run(Button button)
    {
        SynchronizedInvoker.Invoke(() => button.Text = "running");
        Thread.Sleep(5000); // do some important work here
        SynchronizedInvoker.Invoke(() => button.Text = "finished");
    }
}