Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用反射比较列表中的对象_C#_Winforms_Reflection - Fatal编程技术网

C# 使用反射比较列表中的对象

C# 使用反射比较列表中的对象,c#,winforms,reflection,C#,Winforms,Reflection,我有一个“Invoice”WinForm C,其中包含常用的文本框和未绑定的datagridview。 我使用“Invoice”类对象来存储表单字段的值。datagridview行存储在“发票”中的列表属性中 public static bool CompareObjects(object original, object altered) { Type o = original.GetType(); Type a = altered.GetType(); foreac

我有一个“Invoice”WinForm C,其中包含常用的文本框和未绑定的datagridview。 我使用“Invoice”类对象来存储表单字段的值。datagridview行存储在“发票”中的列表<子发票>属性中

public static bool CompareObjects(object original, object altered)
{
    Type o = original.GetType();
    Type a = altered.GetType();

    foreach (PropertyInfo p in o.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        Console.WriteLine("Original: {0} = {1}", p.Name, p.GetValue(original, null));
        Console.WriteLine("Altered: {0} = {1}", p.Name, p.GetValue(altered, null));

        if (p.GetValue(original, null).ToString() != p.GetValue(altered, null).ToString())
        {
            //Console.WriteLine("Not Equal");
            return false;
        }
    }

    return true;
}
我正在使用一个全局类和一个方法,该方法使用反射来循环原始“invoice”对象,并将其与修改后的“invoice”进行比较。如果有任何差异,将通知用户保存发票

上面的方法适用于“Invoice”类的所有属性,但我不知道如何检查列表,在该列表中,它将每个datagridrow的值存储到一个“SubInvoice”类对象中,该对象将其存储为列表中的一个对象

有人能帮我一下吗?我也在stackoverflow和其他论坛中检查过类似的线程,但没有结果


更新:我需要创建一个全局泛型方法来检查所有类型的类。它可以是“发票”、“客户”。其目的是跟踪在任何特定实例中对表单所做的任何更改,并提示用户进行保存。

如果您只是想通知用户保存挂起的更改,那么您应该实现,而不是执行一些黑魔法。

我以前见过的一个技巧是将对象标记为可序列化,然后将它们序列化为字符串并比较字符串。它可能不是最有效的方法,但它快速、简单,适用于几乎任何类型的数据类。它甚至适用于引用其他类的复杂嵌套类


一个不利的一面是,它不会轻易告诉你具体发生了什么变化,只是有些不同。

谢谢大家的帮助

我无意中读到了下面的文章,但仍然渴望通过反射创建一个全局通用方法

如果有人感兴趣,这里有代码

public static bool CompareObjects(object original, object altered)
{
    bool result = true;

    //Get the class
    Type o = original.GetType();
    Type a = altered.GetType();

    //Cycle through the properties.
    foreach (PropertyInfo p in o.GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        Console.WriteLine("Original: {0} = {1}", p.Name, p.GetValue(original, null));
        Console.WriteLine("Altered: {0} = {1}", p.Name, p.GetValue(altered, null));

        if (!p.PropertyType.IsGenericType)
        {
            if (p.GetValue(original, null) != null && p.GetValue(altered, null) != null)
            {
                if (!p.GetValue(original, null).ToString().Equals(p.GetValue(altered, null).ToString()))
                {
                    result = false;
                    break;
                }
            }
            else
            {
                //If one is null, the other is not
                if ((p.GetValue(original, null) == null && p.GetValue(altered, null) != null) || (p.GetValue(original, null) != null && p.GetValue(altered, null) == null))
                {
                    result = false;
                    break;
                }
            }
        }
    }

    return result;
}

public static bool CompareLists<T>(this List<T> original, List<T> altered)
{
    bool result = true;

    if (original.Count != altered.Count)
    {
        return false;
    }
    else
    {
        if (original != null && altered != null)
        {
            foreach (T item in original)
            {
                T object1 = item;
                T object2 = altered.ElementAt(original.IndexOf(item));

                Type objectType = typeof(T);

                if ((object1 == null && object2 != null) || (object1 != null && object2 == null))
                {
                    result = false;
                    break;
                }

                if (!CompareObjects(object1, object2))
                {
                    result = false;
                    break;
                }
            }
        }
        else
        {
            if ((original == null && altered != null) || (original != null && altered == null))
            {
                return false;
            }
        }
    }

    return result;
}

用法:如果!xx.比较对象搜索语音,更改语音|!xx.CompareListssearchedInvoice.SubInvoice,alteredVoice.SubInvoice

如果o和a是不同的类型,则此代码将引发异常,除非a恰好具有与o相同的所有属性。如果任何属性是类或结构,它也不会像您所希望的那样工作,除非它们碰巧重载了ToString以返回一个可以用作相等比较的值。最后,如果a有o没有的属性,它将无法检测到可能的差异。当然可以。o和a都是相同的发票对象。唯一的区别是它们所持有的价值观。例如,o在“原始”中可能有$300.25作为“双倍totalAmount”属性的总值,而a在“更改”中可能有$525.16作为同一属性字段中的总值。“Invoice”类具有double、int、datetime属性和一个List属性,该属性包含一个“subinvoice”类对象列表,这些对象表示datagridview值的每一行。是否检查代码中的任何内容都不强制执行它们是同一类型。您可以添加一行,要求o和a是相同的类型,但仍然不能解决通用代码中的非基本属性问题。@Damith我正在检查。更新:是的,我以前见过。至于Eric,object.Equals方法会检查是否包含一个包含1个其他类的列表是否相等吗?黑魔法,哈哈。这是否适用于未绑定的datatable datagridview?更新:我以前也见过这个例子。我关心的是“Invoice”类的list对象包含另一个类。然后在该类中实现接口。在你的问题中,你是说你有原始对象和修改过的对象,所以不管网格是否有边界,你都在以某种方式修改对象;你怎么知道哪些索引是相同的对象,哪些是全新的,哪些被删除了?实现INotifyPropertyChanged后,您可以使用ObservableCollection监视集合更改。是的,这很有意义。我不可能知道列表中的对象。好的,我会查看ObservableCollection。这对我来说是新的。来想想吧。我不需要知道列表中的哪个对象已更改。只要有任何更改,无论是删除的,还是全新的,我都会提示用户进行更改。我已经签出了INotifyPropertyChanged,我需要在所有类中实现它。您能否提供一个列表中对象的反射示例,这样我就可以使用一种方法来实现相同的结果?