0

我有 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; }
}

我需要使用反射将以下对象放入这样的字符串中:

        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
        };

输出:?method=getAvailableHotel&apiKey=kggdjjgdhgkjghkgjghkjdg&destinationId=LD6J&checkIn=2011-04-20&checkOut=2011-04-24¤cy=EUR&clientNationality=UK&onRequest=false&rooms[0][0][paxType]=Adult&rooms[0][1][paxType]=Adult&rooms [0][2][paxType]=儿童&房间[0][2][年龄]=6&房间[1][0][paxType]=成人&房间[1][1][paxType]=成人&房间[1][2] [paxType]=孩子&房间[1][2][年龄]=8

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

我发现这个Recursively Get Properties & Child Properties Of An Object 但它只是列出了属性而不是值。谢谢。

4

2 回答 2

1

另一种选择是定义自定义序列化机制。

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

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; }
}

使用子集合描述符,例如:

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);
    }
}

您描述的每个类的此接口的实现如下所示:

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 + "]")
            };
        }
    }
}

当然,接口的实现可以由相关类本身提供。

现在,整个序列化部分将是:

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);
        }
    }
}

这种方法不涉及反射,并且更加模块化。您还可以通过添加更多描述符轻松扩展所涵盖类型的数量。

于 2013-10-27T16:50:59.677 回答
-1

这是一个想法。 在这里反思?显示您可以在哪里应用反射。在这种情况下,您可以反映RoomPax的所有属性并使用此信息设置参数,而不是对其进行硬编码。

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)
于 2013-10-27T13:12:35.097 回答