如何创建委托属性 [英] How to Create A Delegate Property

查看:64
本文介绍了如何创建委托属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

美好的一天!我想知道是否可以创建委托属性。我有类似的东西(下面的代码):



Good day all!!! I wanted to find out if it is possible to create a delegate property. I have something like this (code below):

        public delegate void SaveDelegate(DataRow data);
        public delegate void UpdateDelegate(DataRow data);
        public SaveDelegate _RowEditorSave = null;
        public UpdateDelegate _RowEditorUpdate = null;

        public SaveDelegate RowEditorSave
        {
            get { return _RowEditorSave; }
            set { _RowEditorSave = new SaveDelegate(value); }
        }

        public UpdateDelegate RowEditorUpdate
        {
            get { return _RowEditorUpdate; }
            set { _RowEditorUpdate = new UpdateDelegate(value); }
        }


//HOW I'M USING IT BELOW
        this.dgvMemberProvider.RowEditorSave = HandlerMemberProvider.Insert;
        this.dgvMemberProvider.RowEditorUpdate = HandlerMemberProvider.Update;





但是我收到以下警告:



警告8委托实例方法不能为''this''。



我做错了什么???



But I''m getting the following warning:

Warning 8 Delegate to an instance method cannot have null ''this''.

What am I doing wrong???

推荐答案

对不起,我不知道怎么回事重现方法。您没有显示方法 HandlerMemberProvider.Insert HandlerMemberProvider.Update ,并且您也从未显示委托的调用,最后,您没有显示定义所有内容的类/结构。那就是问题所在。



委托实例始终可以是实例方法,并传递隐式的第一个参数 this ,这是对实例的引用实现处理程序方法的类或结构。



但看起来你不太了解你在做什么。



首先, SaveDelegate UpdateDelegate 已经相同的档案。因此,您只需要一种委托类型。此外,在 System 中已经预定义了几种类型的泛型。因此,您可以使用Action< DataRow>代替。但是如果你想为可读性定义一个委托类型,只定义一个,并且不要在其中包含单词Delegate(这与在类名中包含工作class或在类中包含application相同)可执行文件的名称):

Sorry, I don''t know how to reproduce the method. You did not show the methods HandlerMemberProvider.Insert and HandlerMemberProvider.Update, and you also never show the invocation of the delegate, and, finally, you did not show the classes/structures where it all is defined. That''s the problem.

Delegate instances can always be instance methods and pass implicit first parameter this, which is a reference to the instance of the class or structure implementing the handler method.

But it looks like you do not understand quite well what you are doing.

First of all, SaveDelegate and UpdateDelegate has identical profile. So, you need only one delegate type. Besides, several such types are already predefined as generics in System. So, you can use Action<DataRow> instead. But if you want to define a delegate type for readability, define just one, and don''t include the word "Delegate" in it (this is the same as include the work "class" in class name or "application" in the name of executable file):
public delegate void DataUpdater(DataRow data); // something like that
// also consider internal instead of public, is you only use it in the same assembly





然后:



And then:

class MyClass { // or struct

    //...

    public DataUpdater RowEditorSave { get; set; }
    public DataUpdater RowEditorUpdate { get; set; }

    void InvocationDemo(DataRow data) {
        if (RowEditorSave != null) // important!
            RowEditorSave(data);
    }

    //...

} //class MyClass





我还演示了如何正确调用委托实例:注意null。

再次考虑 internal 而不是 public ,如果你不在另一个集合中使用它。



为了解你的理解,这严格等同于:



I also demonstrated how to correctly invoke the delegate instances: be aware of null.
Again, consider internal instead of public, if you don''t use it in a different assembly.

For your understanding, this is strictly equivalent to this:

class MyClass { // or struct

    //...

    public DataUpdater RowEditorSave { get { return rowEditorSave; } set { rowEditorSave = value; } }
    public DataUpdater RowEditorUpdate { get { return rowEditorUpdate; } set { rowEditorUpdate = value; } }
  
    DataUpdater rowEditorSave, rowEditorUpdate;

    void InvocationDemo(DataRow data) {
        if (rowEditorSave != null) // important!
            rowEditorSave(data);th
    }

    //...

} //class MyClass





最后,你应该有这个或另一个类/结构来为委托实例的调用列表添加一些处理程序。对于一个委托实例,您总是可以拥有多个处理程序。你的方法 HandlerMemberProvider.Insert 应该是一些静态或实例方法,接受一个 DataRow 参数(隐式这个是实例方法的第一个参数),它应该返回 void 。换句话说,它应匹配 DataUpdater 签名。



这就是全部。



-SA



Finally, you should have this or another class/structure to add some handlers to the invocation lists of the delegate instances. You can always have more than one handlers for one delegate instance. You method HandlerMemberProvider.Insert should be some static or instance method, accepting one DataRow parameter (implicit this is a first parameter in case of instance method), and it should return void. In other words, it should match DataUpdater signature.

That''s all.

—SA


我只是通过粘贴到我的一个班级并剪掉垃圾来尝试它我没有:

I just tried it by pasting into one of my classes and cutting out the "junk" that I don''t have:
private void button1_Click(object sender, EventArgs e)
    {
    RowEditorSave = Insert;
    RowEditorUpdate = Update;
    }

public delegate void SaveDelegate(DataRow data);
public delegate void UpdateDelegate(DataRow data);
public SaveDelegate _RowEditorSave = null;
public UpdateDelegate _RowEditorUpdate = null;
public void Insert(DataRow dt) { }
public void Update(DataRow dt) { }
public SaveDelegate RowEditorSave
    {
    get { return _RowEditorSave; }
    set { _RowEditorSave = new SaveDelegate(value); }
    }

public UpdateDelegate RowEditorUpdate
    {
    get { return _RowEditorUpdate; }
    set { _RowEditorUpdate = new UpdateDelegate(value); }
    }

我没有错误,编译或运行时间。所以...一个问题。



这是静态类吗?

I get no errors, compilation or run time. So...A question.

Is this in a Static class?


感谢回复人员。我确实是C#的新手。注意到所有意见和建议。



方法插入和更新是静态的:



Thanks for the responses guys. Indeed I''m a bit of a newbie to C#. Took note of all comments and suggestions.

Methods insert and update are static:

public static void Update(DataRow Data)
{
    SetParameterValues(Data);

    try
    {
        _SqlDataAdapter.UpdateCommand.Parameters["@Action"].Value = "UPDATE";
        _SqlDataAdapter.UpdateCommand.Parameters["@User_RowID"].Value = GlobalClass.User_RowID;

        SqlDatabase.ExecuteSqlDataAdapter(_SqlDataAdapter.UpdateCommand);

        if (Convert.ToBoolean(_SqlParameter[5].Value))
        {
            Data.AcceptChanges();
        }
        else
        {
            Data.RejectChanges();
            throw new Exception(Convert.ToString(_SqlParameter[6].Value));
        }

        Data.Table.AcceptChanges();
    }
    catch (Exception ex)
    {
        throw new Exception(ex.Message);
    }
}





这就是我调用的方式:





This is how I was invoking:

public void ShowRowEditor(DataRow data)
{
    firstVisibleCol = this.FirstDisplayedCell.ColumnIndex;

    cellRectangle = RectangleToScreen(this.GetCellDisplayRectangle(firstVisibleCol, this.CurrentRow.Index, false));
    cellPoint = this.GetCellDisplayRectangle(firstVisibleCol, this.CurrentRow.Index, false).Location;
    popupPoint = this.PointToScreen(cellPoint);

    this.RowEditor = new RowEditorForm();
    this.RowEditor.InitRowEditor(this, data, this.DisableOnUpdate);
    this.RowEditor.Location = new Point(popupPoint.X, popupPoint.Y + ((cellRectangle.Height - 26) / 2));

    if (data.RowState == DataRowState.Added)
        this.RowEditor.SaveButtonText = "Save";
    else
        this.RowEditor.SaveButtonText = "Update";

    DialogResult result = this.RowEditor.ShowDialog(this);

    if (result == DialogResult.OK)
    {
        if (data.RowState == DataRowState.Added)
        {
            if (this.RowEditorSave == null)
                return;

            this.RowEditorSave.Invoke(data);
        }
        else
        {
            if (this.RowEditorUpdate == null)
                return;

            this.RowEditorUpdate.Invoke(data);
        }
    }
    else if (result == DialogResult.Cancel)
    {
        if (data.RowState == DataRowState.Added)
        {
            data.Delete();
        }
        else
        {
            data.RejectChanges();
        }
    }
}





我更改了以下内容(和错误/警告现已消失):





I changed the following (and error/warning is now gone):

//public delegate void SaveDelegate(DataRow data);
public delegate void DataDelegate(DataRow data);
//public SaveDelegate _RowEditorSave = null;
//public UpdateDelegate _RowEditorUpdate = null;

public DataDelegate RowEditorSave
{
    get;
    set;
    //get { return _RowEditorSave; }
    //set { _RowEditorSave = new SaveDelegate(value); }
}

public DataDelegate RowEditorUpdate
{
    get;
    set;
    //get { return _RowEditorUpdate; }
    //set { _RowEditorUpdate = new UpdateDelegate(value); }
}


这篇关于如何创建委托属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆