C# 递归地获取属性和值&;对象的子属性和值

C# 递归地获取属性和值&;对象的子属性和值,c#,reflection,C#,Reflection,我有3个类,它们构成了这样一个对象: public class Pax { public PaxType PaxType { get; set; } public int Age { get; set; } public string Title { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } public class R

我有3个类,它们构成了这样一个对象:

public class Pax
{
    public PaxType PaxType { get; set; }
    public int Age { get; set; }
    public string Title { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Room
    {
        public Room()
        {
            Paxes = new List<Pax>();
        }

        public List<Pax> Paxes { get; set; }
    }

public class AvaliableHotelRequest
{
    public AvaliableHotelRequest()
    {
        Rooms = new List<Room>();
    }

    public string Method { get; set; }
    public string ApiKey { get; set; }
    public string DestinationId { get; set; }
    public DateTime CheckIn { get; set; }
    public DateTime CheckOut { get; set; }
    public string Currency { get; set; }
    public string ClientNationality { get; set; }
    public bool OnRequest { get; set; }
    public List<Room> Rooms { get; set; }
}
公共类Pax
{
公共PaxType PaxType{get;set;}
公共整数{get;set;}
公共字符串标题{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
}
公共教室
{
公共房间()
{
Paxes=新列表();
}
公共列表pax{get;set;}
}
公共类AvailableHotelRequest
{
公共AvailableHotelRequest()
{
房间=新列表();
}
公共字符串方法{get;set;}
公共字符串ApiKey{get;set;}
公共字符串DestinationId{get;set;}
公共日期时间签入{get;set;}
公共日期时间签出{get;set;}
公共字符串货币{get;set;}
公共字符串ClientNational{get;set;}
公共bool OnRequest{get;set;}
公共列表室{get;set;}
}
我需要使用反射将以下对象放入字符串中,如下所示:

        var pax1 = new Pax()
        {
            PaxType = PaxType.Adult
        };

        var pax2 = new Pax()
        {
            PaxType = PaxType.Adult
        };

        var pax3 = new Pax()
        {
            PaxType = PaxType.Children,
            Age = 5
        };

        var paxList1 = new List<Pax> {pax1, pax2, pax3};
        var paxList2 = new List<Pax> { pax2, pax3 };
        var rooms = new List<Room>(){new Room(){Paxes = paxList1}, new Room(){Paxes = paxList2}};


        var request = new AvaliableHotelRequest()
        {
            ApiKey = "jhjfjdshsfjkhjhfsdfks",
            CheckIn = DateTime.Now,
            CheckOut = DateTime.Now.AddDays(5),
            ClientNationality = "AU",
            Currency = "EUR",
            DestinationId = "LD6J",
            Method = "getAvailableHotel",
            OnRequest = false,
            Rooms = rooms
        };
var pax1=new Pax()
{
PaxType=PaxType.成人
};
var pax2=新的Pax()
{
PaxType=PaxType.成人
};
var pax3=新的Pax()
{
PaxType=PaxType.Children,
年龄=5岁
};
var paxList1=新列表{pax1,pax2,pax3};
var paxList2=新列表{pax2,pax3};
var Room=new List(){new Room(){Paxes=paxList1},new Room(){Paxes=paxList2};
var request=new availablehotelrequest()
{
ApiKey=“jhjfjdshsfjkhjhfsdfks”,
签入=日期时间。现在,
签出=DateTime.Now.AddDays(5),
clientnational=“AU”,
货币=“欧元”,
DestinationId=“LD6J”,
Method=“getAvailableHotel”,
OnRequest=false,
房间
};
输出: 方法=getAvailableHotel&apiKey=kggdjjgdhgkjghkgjghkjdg&destinationId=LD6J&checkIn=2011-04-20&checkOut=2011-04-24¤cy=EUR&clientnational=UK&onRequest=false&rooms[0][0][paxType]=成人和房间[0][1][paxType]=成人和房间[0][2][paxType]=儿童和房间[0][2][2][年龄]=6和房间[1][paxType][1][paxType]=成人和房间[1][paxType]=儿童及房间[1][2][年龄]=8

一直在尝试不同的方法,但未能通过此问题。 如果你能帮助我,我将不胜感激

我找到了这个 但它只是列出属性,而不是值。 谢谢。

这里有个主意。这里的倒影?显示可以应用反射的位置。 在这种情况下,您可以反映房间或Pax的所有属性,并使用此信息设置参数,而不是对其进行硬编码

List<string> parameters = new List<string>();

// reflection here?
parameters.Add("ApiKey=" + request.ApiKey);
// ... more request parameters here

for (int i = 0; i < request.Rooms.Count; i++)
{
    Room room = request.Rooms[i];

    for (int k = 0; room.Paxes.Count; k++)
    {
        Pax pax = room.Paxes[k];
        string roomParam = "room[" + i + "][" + k + "]";

        // reflection here?
        parameters.Add(roomParam + "[age]=" + pax.Age);
        // ... more pax parameters
    }
}

// we join all parameters get the query string
string query = "?" + String.Join("&", parameters)
List参数=新列表();
//这里的倒影?
参数.Add(“ApiKey=“+request.ApiKey”);
// ... 这里有更多的请求参数
对于(int i=0;i
另一个选项是定义自定义序列化机制

例如,考虑下面的实现(它有一些粗糙的边并且不需要覆盖角情况)。以下接口将某些对象的序列化定义为查询部分:

public interface IQueryPartDescriptor
{
    /// <summary>
    /// Converts the specified object into a string usable as query part.
    /// </summary>
    string ObjectToQueryPart(string prefix, object obj);

    /// <summary>
    /// Describes the properties containing lists of children objects.
    /// </summary>
    IEnumerable<ChildrenCollectionDescriptor> ChildrenListsDescriptors { get; }
}
公共接口IQueryPartDescriptor
{
/// 
///将指定的对象转换为可用作查询部分的字符串。
/// 
字符串ObjectToQueryPart(字符串前缀,objectobj);
/// 
///描述包含子对象列表的属性。
/// 
IEnumerable ChildrenListsDescriptors{get;}
}
具有子集合描述符,如:

public struct ChildrenCollectionDescriptor
{
    private readonly Func<object, IEnumerable<object>> _getChildren;
    private readonly Func<int, string, string> _buildChildPrefix;

    public ChildrenCollectionDescriptor(
        Func<object, IEnumerable<object>> getChildren,
        Func<int, string, string> buildChildPrefix)
        : this()
    {
        _getChildren = getChildren;
        _buildChildPrefix = buildChildPrefix;
    }

    public IEnumerable<object> GetChildren(object parent)
    {
        return _getChildren(parent);
    }

    public string BuildChildPrefix(int childPosition, string accumulatedPrefix)
    {
        return _buildChildPrefix(childPosition, accumulatedPrefix);
    }
}
公共结构ChildrenCollectionDescriptor { 私有只读函数_getChildren; 私有只读Func\u buildChildPrefix; 公共子集合描述符( Func getChildren, Func buildChildPrefix) :此() { _getChildren=getChildren; _buildChildPrefix=buildChildPrefix; } 公共IEnumerable GetChildren(对象父对象) { 返回子项(父项); } 公共字符串BuildChildPrefix(int-childPosition,字符串累加前缀) { 返回_buildChildPrefix(childPosition,累加前缀); } } 您所描述的每个类的此接口的实现如下所示:

public class PaxDescriptor : IQueryPartDescriptor
{
    public string ObjectToQueryPart(string prefix, object obj)
    {
        var pax = (Pax)obj;
        var queryPart = prefix + "[paxType]=" + pax.PaxType;
        if (pax.PaxType == PaxType.Child)
        {
            queryPart += prefix + "[age]=" + pax.Age;
        }

        return queryPart;
    }

    public IEnumerable<ChildrenCollectionDescriptor> ChildrenListsDescriptors
    {
        get { return Enumerable.Empty<ChildrenCollectionDescriptor>(); }
    }
}

public class RoomDescriptor : IQueryPartDescriptor
{
    public string ObjectToQueryPart(string prefix, object obj)
    {
        return String.Empty;
    }

    public IEnumerable<ChildrenCollectionDescriptor> ChildrenListsDescriptors
    {
        get
        {
            return new[]
            {
                new ChildrenCollectionDescriptor(
                    room => ((Room)room).Paxes,
                    (index, roomsPrefix) => roomsPrefix + "[" + index + "]")
            };
        }
    }
}

public class AvaliableHotelRequestDescriptor : IQueryPartDescriptor
{
    public string ObjectToQueryPart(string prefix, object obj)
    {
        var request = (AvaliableHotelRequest)obj;
        return
            "method=" + request.Method + "&" +
            "apiKey=" + request.ApiKey + "&" +
            "destinationID=" + request.DestinationId + "&" +
            "checkIn=" + request.CheckIn.ToString("yyyy-MM-dd") + "&" +
            "checkOut=" + request.CheckOut.ToString("yyyy-MM-dd") + "&" +
            "currency=" + request.Currency + "&" +
            "clientNationality=" + request.ClientNationality + "&" +
            "onRequest=" + request.OnRequest.ToString().ToLower();
    }

    public IEnumerable<ChildrenCollectionDescriptor> ChildrenListsDescriptors
    {
        get
        {
            return new[]
            {
                new ChildrenCollectionDescriptor(
                    request => ((AvaliableHotelRequest)request).Rooms,
                    (index, _) => "&rooms[" + index + "]")
            };
        }
    }
}
公共类PaxDescriptor:IQueryPartDescriptor
{
公共字符串ObjectToQueryPart(字符串前缀,对象obj)
{
var pax=(pax)obj;
var queryPart=前缀+“[paxType]=”+pax.paxType;
if(pax.PaxType==PaxType.Child)
{
queryPart+=前缀+“[age]=”+pax.age;
}
返回查询部分;
}
公共IEnumerable ChildrenListDescriptors
{
获取{return Enumerable.Empty();}
}
}
公共类RoomDescriptor:IQueryPartDescriptor
{
公共字符串ObjectToQueryPart(字符串前缀,对象obj)
{
返回字符串。空;
}
公共IEnumerable ChildrenListDescriptors
{
得到
{
返回新的[]
{
新的子集合描述符(
房间=>((房间)房间)。帕克斯,
(索引,roomsPrefix)=>roomsPrefix+“[”+索引+“]”)
};
}
}
}
公共类AvailableHotelRequestDescriptor:IQueryPartDescriptor
{
公共字符串ObjectToQueryPart(字符串前缀,对象obj)
{
var请求=(AvailableHotelRequest)obj;
返回
“method=“+请求.方法+”&”+
“apiKey=“+reque
public static string ToQuery(object root, IDictionary<Type, IQueryPartDescriptor> partDescriptors)
{
    var queryBuilder = new StringBuilder();
    AddQueryPart(root, String.Empty, partDescriptors, queryBuilder);

    return queryBuilder.Insert(0, '?').ToString();
}

private static void AddQueryPart(
    object obj,
    string prefixInQuery,
    IDictionary<Type, IQueryPartDescriptor> partDescriptors,
    StringBuilder queryBuilder)
{
    var queryPartDescriptor = partDescriptors[obj.GetType()];

    queryBuilder
        .Append(queryPartDescriptor.ObjectToQueryPart(prefixInQuery, obj));

    foreach (var childrenListDescriptor in queryPartDescriptor.ChildrenListsDescriptors)
    {
        var children = childrenListDescriptor.GetChildren(obj).ToList();
        for (var childIndex = 0; childIndex < children.Count; childIndex++)
        {
            var childPrefix = childrenListDescriptor.BuildChildPrefix(childIndex, prefixInQuery);
            AddQueryPart(children[childIndex], childPrefix, partDescriptors, queryBuilder);
        }
    }
}