如何使用属性setter静态实用工具方法的实用程序类(How to use a static uti

2019-09-28 19:35发布

我试图实现双向一个DataGridView和为DGV提供数据的BindingList之间的结合。 某些列尚未反映在基础列表的变化,我想这是因为我还没有提供的属性设置(S),通知的属性更改。 而不是代码的行属性的setter以同样的方式我做的过程财产,我想获得更多的“优雅”,我意识到我坚持....

我偶然发现了一个非常有趣的书面记录了一个更好的方法,我想实现它的概念(请参阅): http://www.gavaghan.org/blog/2007/07/17/use-inotifypropertychanged-与-的BindingList /

下面是Mike的文章中,我想用(在我CBMI.Common项目确立为Utilities.cs)的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace CBMI.Common
{
public static class Utilities
{
    public static bool Set<T>(object owner, string propName,
        ref T oldValue, T newValue, PropertyChangedEventHandler eventHandler)
    {
        // make sure the property name really exists
        if (owner.GetType().GetProperty(propName) == null)
        {
            throw new ArgumentException("No property named '" + propName + "' on " + owner.GetType().FullName);
        }
        if (!Equals(oldValue, newValue))  // we only raise an event if the value has changed
        {
            oldValue = newValue;
            if (eventHandler != null)
            {
                eventHandler(owner, new PropertyChangedEventArgs(propName));
            }
        }
    return true;    // Please NOTE: I had to add this statement to avoid compile error:
        // "not all code paths return a value".
    }
}
}

所以,我对第一个问题 :笔者并没有在他的文章return语句和我说这其中解决了编译器错误。 我猜的事件处理程序执行和回报,这是一个作家遗漏,并作为该方法想要一个布尔返回类型,应返回真。 那是正确的假设?

我的第二个问题说明了什么是C#菜鸟我,当我尝试使用上面这个辅助方法。 我已经编写这个类到名为在同一个项目InputFileInfo.cs(和命名空间)作为上述一个单独的文件:

    using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace CBMI.Common
{
    public class InputFileInfo : INotifyPropertyChanged
    {
    private bool processThisFile;
    public bool Process
    {
        get { return processThisFile; }
        set
        {
        processThisFile = value;
        this.NotifyPropertyChanged("Process");
        }
    }

    public string FileName { get; set; }

    private long rowsReturned;
    public long Rows
    {
        get { return rowsReturned; }
        set
        {
        Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged);
        }

    }
    public string Message { get; set; } 

    // constructor
    public InputFileInfo(string fName)
    {
        Process = true;
        FileName = fName;
        Rows = 0;
        Message = String.Empty;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
    }
}

在这一类中的第2个属性的setter是我尝试使用麦克的静态方法:

Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged);

如果我删除Utilities.Set和如下的代码只是它:

Set(this, "Rows", ref rowsReturned, value, PropertyChanged);

..then我得到的编译器抱怨“名‘设置’在目前情况下不存在”。

我尝试添加一个使用工具; 指令 ,但没有解决问题。

最后,我不明白的参数:裁判牛逼的属性oldValue,T NEWVALUE
也不是参数调用值,其中所述Set方法被调用。

有人可以帮我在这段代码,这些多混乱,所以我可以使用这些更高级的想法?

----编辑UPDATE ----两个很好的答案,帮助我得到这个工作。 上述在原岗位的“第二个问题”仍然是一个有点难以捉摸。 增加了对每个请求对如何打包这个,所以我可以用简单的调用语法在迈克的原创文章“最佳实践”的意见。 也就是说,我正在寻找援引“帮手”仅方法名称的静态方法。 我想了解如何调用,如:

set
{
    Set(this, "Rows", ref rowsReturned, value, PropertyChanged);
}

而不必编写为:

set
{
    Utilities.Set(this, "Rows", ref rowsReturned, value, PropertyChanged);
}

我通过编码Utilities.Set得到了这个工作,但我想这个问题摇身一变比特到- “?与类名它们‘’我在哪里可以把静态方法和如何给他们打电话,所以我没有”资格 我想了解如何包装通常是有用的“效用”型方法不需要对象的实例。 在这种情况下,静态方法被调用设置,但我希望能够添加其他静态方法,例如:

public static int HelpfulMethodXXXX(string s, int num)

我有一个单独编译的DLL只包含类文件(S)(Vstudio项目)。 最后,我想认为我可以在其他应用程序中使用这个类。

哪里是声明这些类的静态方法,使得它们可以被调用为最佳地点:

int i = HelpfulMethodXXXX("Sample", testNumber);

代替:

int i = ContainingClassName.HelpfulMethodXXXX("Sample", testNumber);

Answer 1:

1:所有非void的方法需要有明确的返回语句。

2:CMBI.Common是命名空间。 Utilities是你的类的名称。 ()设置为你的类的函数。

呼叫设置()才有意义的实用工具类的上下文。 集()不是全局命名空间的一部分 - 因此,如果你想调用()设置的实用工具类之外,你必须指定你想要的Utilities.Set(),而不是SomethingElse.Set() 。 (内部实用程序,编译器明白设置()是指Utilities.Set())。

使用语句只能包括命名空间(CMBI.Common),或特定的类命名空间内,如果你不想在命名空间(CMBI.Common.Utilities)每类。 他们不能,然而,把一个类的函数成为一个全球性的功能。

3:T是指该功能运行在通用类型的名称。 http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx

泛型允许相同的代码来处理,比方说,整数的集合,和字符串的集合,而强制执行编译时类型安全(编译器会给出一个错误,如果你试图把一个整数转换成字符串的集合。)

REF表示参数作为基准通过 - 和一个函数的主体内的参数所做的更改将传播到该函数的调用者的上下文参数的值。



Answer 2:

  • 它看起来像返回类型应该从改变boolvoid ,因为它不会出现永远返回不同的值。

  • 是的, Utilities.Set是正确的语法。 没有模拟在Java静态导入,例如,让你有一个类来限定它。 你可以使用扩展方法,如果你选择,并能够调用类的方法this.Set(...)代替。 要做到这一点,只需添加this关键字在你的第一个参数的前面Set方法:

 

public static bool Set<T>(this object owner, string propName,
    ref T oldValue, T newValue, PropertyChangedEventHandler eventHandler)
  • ref T oldValue意味着你可以通过它类型的变量T和它将写入的旧值到它(换言之,通过按引用值类型)。 这样,您就可以找出什么是oldValue了。 (虽然在我看来,一个out参数会更有意义。)

  • T newValue是你正试图将其设置为新值。 如果你问什么T是,它是一个通用型并作为whta类型真的是一个占位符。 它计算出哪种类型的自动根据您传递给它的参数的类型。 (如果你传递一个string ,T的作用完全一样,如果你使用的string ,而不是T 。)

  • value是在C#中,只有具有特殊含义的特殊关键字set您定义的属性的访问。 这是您要分配给属性的值。



文章来源: How to use a static utility method for property setters in a utility class