Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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#_List_Sorting_Generics - Fatal编程技术网

C# 如何使用可选属性顺序按对象中的属性对列表进行排序

C# 如何使用可选属性顺序按对象中的属性对列表进行排序,c#,list,sorting,generics,C#,List,Sorting,Generics,假设我有一个基类和两个派生类 public abstract class BaseClass { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public string Owner { get; set; } public DateTime DateAdded { get; set; } }

假设我有一个基类和两个派生类

public abstract class BaseClass 
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public string Owner { get; set; }

    public DateTime DateAdded { get; set; }
}

public class Foo : BaseClass
{
    [CustomAttr(Order = 2)]
    public string Country { get; set; }

    [CustomAttr(Order = 5)]
    public decimal Amount { get; set; }

    public string Other { get; set; }
}

public class Bar : BaseClass
{
    [CustomAttr(Order = 3)]
    public string Organization { get; set; }

    [CustomAttr(Order = 1)]
    public string Keywords { get; set; }
}
默认情况下,属性的顺序取决于它们在类中的声明方式,因此如果在基类中,因为没有[CustomAttrOrder=n],则假定这是正确的顺序

现在,由于在两个派生类中,定义了一个自定义属性,该属性将标识行为应按以下顺序排序的属性顺序:

身份证件 国 名称 描述 数量 物主 添加日期 另外 因此,那些具有CustomAttr[Order=n]的属性应该按其属性顺序排列,对于那些没有的属性,我们假设它们的顺序正确。如果我使用Bar类,这也应该有类似的行为

这个用例是我需要在列表中具有正确的类属性顺序,才能在excel文件中具有正确的列顺序

我所做的是,我必须将CustomAttr[Order=n]添加到所有属性中以对它们进行排序,但是这是一件乏味的事情,如果您尝试更改其中一个属性顺序,则需要更改所有属性的顺序


有什么方法可以实现这一点吗?

请参阅此示例,了解如何在system.Linq中使用列表进行订购

class Program
{

    class test
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }

        public string Owner { get; set; }

        public DateTime DateAdded { get; set; }
    }
    static void Main(string[] args)
    {


        List<test> listOrder = new List<test>();
        listOrder.Add(new test() { Id = 1, Name = "john", Description = "test", Owner = "test", DateAdded = DateTime.Now });
        listOrder.Add(new test() { Id = 1, Name = "max", Description = "test1", Owner = "test1", DateAdded = DateTime.Now });
        listOrder.Add(new test() { Id = 1, Name = "phil", Description = "test2", Owner = "test2", DateAdded = DateTime.Now });

        List<test> sortbyName = listOrder.OrderBy(item => item.Name).ToList();

        List<test> sortbyDescription = listOrder.OrderBy(item => item.Description).ToList();

        List<test> sortbyOwner = listOrder.OrderBy(item => item.Owner).ToList();

    }
}

您可以使用反射按声明的顺序读取类的所有属性的名称。然后您可以在逻辑中对此进行详细说明,并相应地对字段进行排序

请尝试以下操作:

PropertyInfo[] propertyInfos = typeof(Bar).GetProperties();
foreach (var propInfo in propertyInfos)
    Console.WriteLine(propInfo.Name);
这将写入Bar类中的所有属性这只是一个示例,您可以用任何类替换它,包括从其超类基类继承的属性。预期输出:

Organization
Keywords
Id
Name
Description
Owner
DateAdded
请注意,该方法首先列出类中的属性,然后在层次结构中列出每个超类,这就是为什么Bar的成员在基类的成员之前列出的原因。您可以根据需要对代码进行详细说明,以更改顺序

下面的非优化代码首先创建给定类的所有层次结构的列表,从基类到给定的T类。然后,它迭代每个类,只发现在每个类中定义的属性。我将向GetProperties方法传递一个参数,说明我只需要是公共的、实例/非静态的,并且在我当前咨询的特定类上声明

预期输出将是按以下顺序排列的属性:

Id
Name
Description
Owner
DateAdded
Organization
Keywords
通过CustomAttr属性,您可以了解字段的声明顺序及其自定义顺序。现在,您可以实现一种排序方法,根据您的需要,根据字段的声明顺序和CustomAttr顺序对字段进行排序


但我想这超出了我的回答的范围,我的回答旨在向您展示如何获得属性声明的顺序,从基类到任何给定的特定类。

我创建了一个通用解决方案,通过读取您的属性并创建一个比较器,将按照属性顺序进行比较我正在读比较器的反射属性。在比较时,我一个接一个地取一个属性,当等于零时,我转到下一个属性。 该逻辑还与继承一起工作,因此即使在基类上,也可以使用CustomAttr

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

public class CustomAttr : Attribute
{
    public CustomAttr():base()
        {}

    public CustomAttr(int Order)
    {
        this.Order = Order;
    }
    public int Order {get ; set ; }

}
public abstract class BaseClass
{
    public int Id { get; set; }

    [CustomAttr(Order = 20)]
    public string Name { get; set; }

    public string Description { get; set; }

    public string Owner { get; set; }

    public DateTime DateAdded { get; set; }
}

public class Foo : BaseClass
{
    [CustomAttr(Order = 2)]
    public string Country { get; set; }

    [CustomAttr(Order = 5)]
    public decimal Amount { get; set; }

    public string Other { get; set; }
}

public class Bar : BaseClass
{
    [CustomAttr(Order = 3)]
    public string Organization { get; set; }

    [CustomAttr(Order = 1)]
    public string Keywords { get; set; }
}
class app
{


    static void Main()
    {
        List<Bar> listToOrder = new List<Bar>();
        listToOrder.Add(new Bar() { Id = 5, Keywords = "Hello", Organization = "Arlando" });
        listToOrder.Add(new Bar() { Id = 12, Keywords = "Table", Organization = "Fuelta" , Name = "Deep"});
    listToOrder.Add(new Bar() { Id = 12, Keywords = "Table", Organization = "Fuelta", Name = "Inherit" });
    listToOrder.Add(new Bar() { Id = 1, Keywords = "Muppet", Organization = "Coke" });
        listToOrder.Add(new Bar() { Id = 6, Keywords = "Grumpy", Organization = "Snow" });
        listToOrder.Add(new Bar() { Id = 9, Keywords = "Johny", Organization = "White" });
        listToOrder.Add(new Bar() { Id = 12, Keywords = "Table", Organization = "Bruno" });
        listToOrder.Add(new Bar() { Id = 12, Keywords = "Table", Organization = "Fuelta" });
        listToOrder.Add(new Bar() { Id = 7, Keywords = "Set", Organization = "Voltra" });
        listToOrder.Add(new Bar() { Id = 45, Keywords = "Brr", Organization = "Elvis" });
        listToOrder.Add(new Bar() { Id = 15, Keywords = "Tsss", Organization = "Marion" });

        OrderComparer<Bar> myOrder = new OrderComparer<Bar>();
        listToOrder.Sort(myOrder);

        foreach (Bar oneBar in listToOrder)
        {
            Console.WriteLine(oneBar.Id + " " + oneBar.Keywords + " " + oneBar.Organization);
        }

        Console.ReadKey();
    }

    private class OrderComparer<T> : IComparer<T>
    {
        SortedList<int, PropertyInfo> sortOrder = new SortedList<int, PropertyInfo>();

        public OrderComparer()
        {
            Type objType = typeof(T);
            foreach (PropertyInfo oneProp in objType.GetProperties())
            {
                CustomAttr customOrder = (CustomAttr) oneProp.GetCustomAttribute(typeof(CustomAttr), true);
                if (customOrder == null) continue;
                sortOrder.Add(customOrder.Order, oneProp);
            }
        }
        public int Compare(T x, T y)
        {
            Type objType = typeof(T);
            int result = 0;
            int i = 0;

            while (result == 0 && i < sortOrder.Count)
            {
                result = ((IComparable)sortOrder.ElementAt(i).Value.GetValue(x)).CompareTo(sortOrder.ElementAt(i).Value.GetValue(y));
                i++;
            }

            return result;
        }
    }
}
你可以发布CustomAttr的代码,因为它看起来与你的问题相关。另外,如果没有指定,你必须在那里写一些逻辑来“假设”默认顺序。
Id
Name
Description
Owner
DateAdded
Organization
Keywords
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

public class CustomAttr : Attribute
{
    public CustomAttr():base()
        {}

    public CustomAttr(int Order)
    {
        this.Order = Order;
    }
    public int Order {get ; set ; }

}
public abstract class BaseClass
{
    public int Id { get; set; }

    [CustomAttr(Order = 20)]
    public string Name { get; set; }

    public string Description { get; set; }

    public string Owner { get; set; }

    public DateTime DateAdded { get; set; }
}

public class Foo : BaseClass
{
    [CustomAttr(Order = 2)]
    public string Country { get; set; }

    [CustomAttr(Order = 5)]
    public decimal Amount { get; set; }

    public string Other { get; set; }
}

public class Bar : BaseClass
{
    [CustomAttr(Order = 3)]
    public string Organization { get; set; }

    [CustomAttr(Order = 1)]
    public string Keywords { get; set; }
}
class app
{


    static void Main()
    {
        List<Bar> listToOrder = new List<Bar>();
        listToOrder.Add(new Bar() { Id = 5, Keywords = "Hello", Organization = "Arlando" });
        listToOrder.Add(new Bar() { Id = 12, Keywords = "Table", Organization = "Fuelta" , Name = "Deep"});
    listToOrder.Add(new Bar() { Id = 12, Keywords = "Table", Organization = "Fuelta", Name = "Inherit" });
    listToOrder.Add(new Bar() { Id = 1, Keywords = "Muppet", Organization = "Coke" });
        listToOrder.Add(new Bar() { Id = 6, Keywords = "Grumpy", Organization = "Snow" });
        listToOrder.Add(new Bar() { Id = 9, Keywords = "Johny", Organization = "White" });
        listToOrder.Add(new Bar() { Id = 12, Keywords = "Table", Organization = "Bruno" });
        listToOrder.Add(new Bar() { Id = 12, Keywords = "Table", Organization = "Fuelta" });
        listToOrder.Add(new Bar() { Id = 7, Keywords = "Set", Organization = "Voltra" });
        listToOrder.Add(new Bar() { Id = 45, Keywords = "Brr", Organization = "Elvis" });
        listToOrder.Add(new Bar() { Id = 15, Keywords = "Tsss", Organization = "Marion" });

        OrderComparer<Bar> myOrder = new OrderComparer<Bar>();
        listToOrder.Sort(myOrder);

        foreach (Bar oneBar in listToOrder)
        {
            Console.WriteLine(oneBar.Id + " " + oneBar.Keywords + " " + oneBar.Organization);
        }

        Console.ReadKey();
    }

    private class OrderComparer<T> : IComparer<T>
    {
        SortedList<int, PropertyInfo> sortOrder = new SortedList<int, PropertyInfo>();

        public OrderComparer()
        {
            Type objType = typeof(T);
            foreach (PropertyInfo oneProp in objType.GetProperties())
            {
                CustomAttr customOrder = (CustomAttr) oneProp.GetCustomAttribute(typeof(CustomAttr), true);
                if (customOrder == null) continue;
                sortOrder.Add(customOrder.Order, oneProp);
            }
        }
        public int Compare(T x, T y)
        {
            Type objType = typeof(T);
            int result = 0;
            int i = 0;

            while (result == 0 && i < sortOrder.Count)
            {
                result = ((IComparable)sortOrder.ElementAt(i).Value.GetValue(x)).CompareTo(sortOrder.ElementAt(i).Value.GetValue(y));
                i++;
            }

            return result;
        }
    }
}