我有一个WebApi,它有一些接受XMLDocument值的动作方法。在这些函数中,我将XML转换为AnonymousObject
,然后,我做了我的逻辑。
现在,我得到了带有空属性的XML,我需要做一个检查,可以检查该匿名对象中的所有属性,如果它们为null或为空,我做了一些但是它没有用,但是,我传递了一个带有空属性的XML。
<Students>
<Student ID="" Name="" />
<Student ID="" Name="" />
</Students>
这是我得到的XML输入的一个示例,并且还有其他一些形式,因此,我编写了一个函数,在将XML反序列化为匿名对象后,检查属性是否为空,如下所示:
//This handles the conversion from XML to the anonymous object
XDocument doc;
using (var sr = new StringReader(request.InnerXml))
{
doc = XDocument.Load(sr);
}
var clientList = doc.Descendants()
.Where(d => string.Equals(d.Name.LocalName, "Student", StringComparison.OrdinalIgnoreCase))
.Select(
d =>
new
{
studentId = d.Attributes().SingleOrDefault(a =>
string.Equals(a.Name.LocalName, "ID", StringComparison.OrdinalIgnoreCase))
?.Value,
studentName = d.Attributes().SingleOrDefault(a =>
string.Equals(a.Name.LocalName, "Name", StringComparison.OrdinalIgnoreCase))
?.Value
}).ToList();
然后我编写了该函数,它应该验证匿名对象的属性,都应该有一个值,但是如果我传递了上面的XML,它将返回 FALSE ,好像没有空值的属性:
public static bool IsAnyNullOrEmpty(object objectToBeChecked)
{
try
{
foreach (PropertyInfo pi in objectToBeChecked.GetType().GetProperties())
{
if (pi.PropertyType == typeof(string))
{
string value = (string)pi.GetValue(objectToBeChecked);
if (string.IsNullOrEmpty(value))
{
return true;
}
}
}
return false;
//return objectToBeChecked.GetType().GetProperties()
// .Where(pi => pi.GetValue(objectToBeChecked) is string)
// .Select(pi => (string) pi.GetValue(objectToBeChecked))
// .Any(string.IsNullOrEmpty);
}
catch (Exception ex)
{
return true;
}
}
有什么建议吗?
调试时我注意到了:
<>f__AnonymousType3`1
Name = "<>f__AnonymousType3`1" FullName = "<>f__AnonymousType3`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
答案 0 :(得分:2)
我强烈建议使用命名类而不是匿名类。显然,您对xml中的实例所展示的属性有一定的了解,因此无需隐藏这些知识。
想象一下,有一天你不仅需要字符串属性,还需要数字。然后你必须重新发明你的逻辑的很大一部分,不仅仅是验证,而只是实际的工作与对象。
我想你想做的不仅仅是验证你的对象。你肯定想与他们一起做。为了做到这一点,你需要知道他们揭露的成员。在您当前的实现中,它们只是objects
,不会给客户带来太多暴露。所以为了做任何事你需要这样的东西:
var a = ((theType) myInstance).StudentName;
但是您已经丢失了有关theType
实际上是什么的所有信息,因此您可以使用该对象调用ToString
,Equals
和其他一些来自{{1}的成员}}
在您的特殊情况下,您已经知道xml中的实例具有object
- 和StudentName
- 属性。那你为什么要把它丢掉呢?就好像你不知道那样?
截至MSDN:
要将匿名类型或包含匿名类型的集合作为方法的参数传递,可以将参数声明为类型对象。但是,这样做会破坏强类型的目的。如果你必须 存储查询结果或将它们传递到方法边界之外,考虑一下 使用普通的命名结构或类而不是匿名类型。
答案 1 :(得分:2)
我解决了这个问题:
public static bool IsAnyNullOrEmpty(object objectToBeChecked, params string[] parametersToBeChecked)
{
foreach (var obj in (IEnumerable)objectToBeChecked)
{
foreach (var pi in obj.GetType().GetProperties())
{
if (parametersToBeChecked.Contains(pi.Name))
{
var value = (string)pi.GetValue(obj);
if (string.IsNullOrEmpty(value))
{
return true;
}
}
}
}
return false;
}
这将获取您要检查的对象(匿名对象)和属性名称,这对我有用。
答案 2 :(得分:1)
如果要在某个方法中传递对象,则需要使用具体的类实现。 复制xml结构,让Visual Studio为您创建反序列化类。 编辑 - &gt;选择性粘贴 - &gt;将Xml粘贴为Class
如果你知道你的Xml-Structur,为什么要放弃这些信息。