检查 IEnumerable有反射
编辑
这个问题的基本版本是,如果我有一些对象o
,我将如何检查o是否是实现IEnumerable<的某种类型;string>
带有反射?最初的问题更加具体,但对上述问题的回答也同样好。抱歉,如果我在这个问题上提供了太多细节
END EDIT
以下是一个人为的 ValueInjecter POC。除了最底部的 isCollectionMapping 方法之外,一切都运行良好。我试图让它返回 true 当且仅当源属性和目标属性都是实现 IEnumerable
的任何对象时。
我尝试过 IsAssignableFrom
和 IsInstanceOfType
,但似乎都不起作用。
其他一切都有效,因为当我取消注释该方法的第二行以显式检查名称“Children”的属性时,它工作正常。
注意 - 我确实知道这个示例存在问题。也就是说,我试图检查任何旧的 IEnumerable<>
但始终知道足够的信息来返回 List<>
;目前这只是一个愚蠢的概念证明。
[TestClass]
public class UnitTest1 {
[TestMethod]
public void TestMethod1() {
List<string> strings = new List<string>();
Subject S = new Subject() {
id = 1,
SubjectName = "S1",
Children = { new Subject() { id = 2, SubjectName = "S1a" },
new Subject() { id = 3, SubjectName = "S1b", Children = { new Subject() { id = 4} } } }
};
SubjectViewModel VM = (SubjectViewModel)new SubjectViewModel().InjectFrom<CollectionToCollection>(S); ;
Assert.AreEqual(2, VM.Children.Count);
Assert.AreEqual(1, VM.Children.Single(s => s.id == 3).Children.Count);
}
}
public class Subject {
public Subject() {
Children = new List<Subject>();
}
public string SubjectName { get; set; }
public int id { get; set; }
public List<Subject> Children { get; set; }
}
public class SubjectViewModel {
public SubjectViewModel() {
Children = new List<SubjectViewModel>();
}
public string SubjectName { get; set; }
public int id { get; set; }
public List<SubjectViewModel> Children { get; set; }
}
public class CollectionToCollection : Omu.ValueInjecter.ConventionInjection {
protected override bool Match(ConventionInfo c) {
return c.TargetProp.Name == c.SourceProp.Name;
}
protected override object SetValue(ConventionInfo c) {
if (isCollectionMapping(c))
return (c.SourceProp.Value as IEnumerable<Subject>).Select(s => (SubjectViewModel)(new SubjectViewModel().InjectFrom<CollectionToCollection>(s))).ToList();
else
return c.SourceProp.Value;
}
private bool isCollectionMapping(ConventionInfo c) {
return c.SourceProp.Value.GetType().IsInstanceOfType(typeof(IEnumerable<Subject>)) && c.TargetProp.Value.GetType().IsAssignableFrom(typeof(IEnumerable<SubjectViewModel>));
//return c.SourceProp.Name == "Children" && c.TargetProp.Name == "Children";
}
}
EDIT
The bare-bones version of this question is, if I have some object o
, how would I check to see if o is of some type that implements IEnumerable<string>
with reflection? The original question is much more specific, but an answer to the above would be just as good. Sorry if I gave too much detail on this question
END EDIT
The following is a contrived ValueInjecter POC. Everything works well except for the isCollectionMapping
method at the very bottom. I'm trying to get it to return true if and only if both the source and target property are any object that implement IEnumerable<respectiveTypes>
.
I've tried IsAssignableFrom
and also IsInstanceOfType
, but neither seems to work.
Everything else works since when I uncomment the second line of the method to check explicitly for properties of name "Children", it works fine.
Note - I do know there are issues with this example. Namely, I'm trying to check for any old IEnumerable<>
but yet always knowing enough to return List<>
; it's just a silly proof of concept at this point.
[TestClass]
public class UnitTest1 {
[TestMethod]
public void TestMethod1() {
List<string> strings = new List<string>();
Subject S = new Subject() {
id = 1,
SubjectName = "S1",
Children = { new Subject() { id = 2, SubjectName = "S1a" },
new Subject() { id = 3, SubjectName = "S1b", Children = { new Subject() { id = 4} } } }
};
SubjectViewModel VM = (SubjectViewModel)new SubjectViewModel().InjectFrom<CollectionToCollection>(S); ;
Assert.AreEqual(2, VM.Children.Count);
Assert.AreEqual(1, VM.Children.Single(s => s.id == 3).Children.Count);
}
}
public class Subject {
public Subject() {
Children = new List<Subject>();
}
public string SubjectName { get; set; }
public int id { get; set; }
public List<Subject> Children { get; set; }
}
public class SubjectViewModel {
public SubjectViewModel() {
Children = new List<SubjectViewModel>();
}
public string SubjectName { get; set; }
public int id { get; set; }
public List<SubjectViewModel> Children { get; set; }
}
public class CollectionToCollection : Omu.ValueInjecter.ConventionInjection {
protected override bool Match(ConventionInfo c) {
return c.TargetProp.Name == c.SourceProp.Name;
}
protected override object SetValue(ConventionInfo c) {
if (isCollectionMapping(c))
return (c.SourceProp.Value as IEnumerable<Subject>).Select(s => (SubjectViewModel)(new SubjectViewModel().InjectFrom<CollectionToCollection>(s))).ToList();
else
return c.SourceProp.Value;
}
private bool isCollectionMapping(ConventionInfo c) {
return c.SourceProp.Value.GetType().IsInstanceOfType(typeof(IEnumerable<Subject>)) && c.TargetProp.Value.GetType().IsAssignableFrom(typeof(IEnumerable<SubjectViewModel>));
//return c.SourceProp.Name == "Children" && c.TargetProp.Name == "Children";
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
简单如下:顺便
说一下,您当前的代码无法正常工作,因为它正在逆转可分配关系的测试(就好像该方法被称为 IsAssignableTo 一样),即它假设:
暗示:
实际上,实际的含义是:
在这种情况下,您需要测试该类型是否实现了通用接口的构造版本:
As simple as:
By the way, your current code isn't working because it is reversing the testing of the assignability relationship (as though the method were called
IsAssignableTo
), i.e. It is assuming that:implies:
In reality, the actual implication is that:
In this case, you need to test if the type implements a constructed version of the generic interface:
像这样:
Like this:
我可能错过了一些东西(没有阅读您的整个代码示例),但您似乎不需要在这里反思。
直接使用怎么样:
如果您不知道具体类型,请使用泛型:
或者如果您需要使用接口,请这样做(节省强制转换):
I could have missed something (didn't read your whole code sample), but it doesn't seem like you need reflection here.
How about just using:
If you don't know the specific type, use generics:
Or if you need to use the interface, do it this way (saves a cast):