C# 递归地获取属性和值&;对象的子属性和值
我有3个类,它们构成了这样一个对象: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
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);
}
}
}