我有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
};
输出: ?方法= getAvailableHotel&安培; apiKey = kggdjjgdhgkjghkgjghkjdg&安培;目标-ID = LD6J&安培;签= 2011-04-20&安培;在checkOut = 2011-04-24&安培;货币= EUR&安培; clientNationality = UK&安培; onRequest =假安培;房间[0] [0] [paxType ] =成人及房间[0] [1] [paxType] =成人及房间[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 但它只是列出属性而不是值。 感谢。
答案 0 :(得分: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);
}
}
}
这种方法不涉及反射,而且更加模块化。您还可以通过添加更多描述符来轻松扩展所涵盖类型的数量。
答案 1 :(得分:-1)
这是一个想法。 反射在这里?显示您可以应用反射的位置。 在这种情况下,您可以反映 Room 或 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)