【问题标题】:Update a specific property with generics (Winform C#)使用泛型更新特定属性 (Winform C#)
【发布时间】:2016-02-20 09:43:48
【问题描述】:

抱歉,因为我是泛型新手(我认为在这种情况下需要这样做)。

我想将 BindingList 变量传递给对已定义属性执行更新的方法,然后返回通过/失败(真/假)值。这似乎比我想象的要难,所以可以使用一些帮助。这是工作和非工作代码。

首先,我有一个带有 BindingList 的类(工作):

public class BookMetaData : INotifyPropertyChanged
{
    private string _bookMetaDataTitle;
    [DescriptionLocalized(typeof(ResourcesClassBooks), "BookMetaDataTitleComment")]
    [DisplayNameLocalized(typeof(ResourcesClassBooks), "BookMetaDataTitleDisplayName")]
    public string BookMetaDataTitle { get { return _bookMetaDataTitle; } set { SetField(ref _bookMetaDataTitle, value, "BookMetaDataTitle"); } }

    #region handle property changes
    public event PropertyChangedEventHandler PropertyChanged;
    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        //if the value did not change, do nothing.
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        //the value did change, so make the modification.
        field = value;
        return true;
    }
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

接下来,我创建一个表示绑定列表的变量(工作):

BindingList<BookMetaData> bookMetaData = new BindingList<BookMetaData>(); //metadata for the books

准备发送类变量和特定属性以更新到泛型方法。请注意,这在技术上有效,但其余代码无效:

private bool Test()
{
    //the code below would probably be in a foreach loop and would not pass a single index.
    ProcessBookTitle(bookMetaData, 0, typeof(BookMetaData).GetProperty(nameof(BookMetaData.BookMetaDataCoverage)));
    return true;
}

我想要这个泛型方法(它被称为方法吗?)来更新 BindingList 类变量的指定属性。如果一般业务逻辑出现问题,则返回 false。否则,返回 true(不工作):

private void ProcessBookTitle<T>(BindingList<T> bindingList, int classIndex, PropertyInfo prop)
{
    try
    {
        //do some things...
        //If I manually wrote the next line, it would look like this:
        //bookMetaData[0].BookMetaDataTitle = "My Book Title";
        bindingList[classIndex].prop = "My Book Title"; //error = 'T' does not contain the information for 'prop'...
        //maybe do some other things...
        return true; //cannot find a way to return bool.
    }
        catch
        {
            //something went wrong somewhere, so return false.
            return false; //does not work because cannot return a bool.
        }
    }

有没有办法可以将类变量的名称和属性发送到另一个方法?另外,是否可以在返回 bool 的方法中执行此操作(或其他返回成功或失败的方法)?

提前感谢您提供的任何帮助。

编辑:返回布尔值的要求是确保传递方法知道整个过程是否成功。更新了代码以显示这一点。

【问题讨论】:

  • 你可以使用反射。但是您如何决定返回truefalse?设置属性值失败是什么意思?如果属性设置器中抛出异常?
  • 这对我来说是一个很好的澄清点。您应该假设在该方法中有其他登录,可以执行诸如从磁盘读取文件或解析信息等功能。如果在该过程中出现故障,则返回 true 或 false。
  • 哪种方法? SetField 方法?例如BookMetaDataTitle 属性调用此方法但忽略返回值。
  • 也许我没有使用正确的术语。我所说的Test 方法调用ProcessBookTitle 方法。当ProcessBookTitle 运行时,我希望它更新传递的类变量的特定属性。我还希望Test 方法知道所有代码都在ProcessBookTitle 方法中正常运行。这有意义吗?如果我以错误的方式使用术语方法,我深表歉意。

标签: c# winforms generics


【解决方案1】:

@Yacoub Massad 提到,您可以为此使用反射。如果你想知道它是怎么回事。我们在这里所做的是获取泛型类型 T 的类型并访问其属性信息。现在,既然您提到了从文件读取、解析信息等,我建议您查看Delegate Actions With Return Values。但这本身就是另一个故事。

    static private bool ProcessBookTitle<T>(BindingList<T> bindingList, int classIndex, string propertyName) 
        where T : class
    {
        try
        {
            Type type = typeof(T);
            PropertyInfo propertyInfo = type.GetProperty(propertyName);

            object val = "Do some processing whatever here.";

            propertyInfo.SetValue(bindingList[classIndex], Convert.ChangeType(val, propertyInfo.PropertyType), null);

            return true;
        }
        catch (Exception ex)
        {
            // do something with the exception

            return false;
        }
    }

【讨论】:

  • 或者您可以简单地向名为 val 类型对象的方法添加另一个参数并将其分配给 Convert.ChangeType(val ...
  • 非常感谢@John,这行得通。我进一步增强了您的代码,因此我不必使用字符串调用。调用方法如下所示:ProcessBookTitle(bookMetaData, 0, typeof(BookMetaData).GetProperty(nameof(BookMetaData.BookMetaDataTitle))); 这允许我删除where T : classType type = typeof(T); 行和PropertyInfo propertyInfo = type.GetProperty(propertyName); 行。你觉得这有什么问题吗?代码运行,所以我觉得还可以:-)
  • 如果它有效,那么它就有效。完全没有问题。但是我们使用泛型 的原因是该方法适用于不同的类,而不仅仅适用于 BookMetaData 类型。如果您有另一个 XXX 类型的列表,您可以使用相同的方法。我建议尽可能使用上面发布的通用版本,以便将来如果您需要为不同的类提供相同的功能,您可以重复使用它。
  • 好吧,既然您将其命名为 ProcessBookTitle,那么您的修改似乎更合适。 :-)
  • 好的,非常感谢。最终,它的名称可能会像GetSingleNodeFromHtml 这样更通用。非常感谢您快速且非常有帮助的回复。我每天都在学习很多东西,通过学习,我的意思是有时会绊倒:-)
猜你喜欢
  • 2017-12-31
  • 1970-01-01
  • 2016-07-06
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多