C# 动态转换为IEnumerable<;T>;或T
我有一个类接受C# 动态转换为IEnumerable<;T>;或T,c#,generics,reflection,C#,Generics,Reflection,我有一个类接受T,有一个方法接受HttpResponseMessage并修改响应中的内容 public class MyClass<T> { HttpResponseMessage Modify(HttpResponseMessage response) { T content; if(response.TryGetContentValue(out content)) { DoSomethingWithContent(
T
,有一个方法接受HttpResponseMessage
并修改响应中的内容
public class MyClass<T> {
HttpResponseMessage Modify(HttpResponseMessage response) {
T content;
if(response.TryGetContentValue(out content)) {
DoSomethingWithContent(content);
}
return response;
}
public void DoSomethingWithContent(T content) {}
public void DoSomethingWithContent(IEnumerable<T> content) {}
}
您可以使用
is
来确定使用哪种情况
if (content is IEnumerable<T>)
DoSomethingWithContent((IEnumerable<T>)content);
else
DoSomethingWithContent(content);
是的,你的设计有圆度问题。如果将
MyClass
初始化为例如MyClass
,则T=List
,因此实际上不会调用重载定义。实际上,您需要做的是只使用一个方法,但有一个子句来测试T
是否实现了IEnumerable
。你可以这样做
if (content is IEnumerable<T>)
if(内容是IEnumerable)
但我不完全确定这是否可行,因为您甚至可能需要指定IEnumberable使用的类型。如果是这种情况,那么检查它是否实现了非泛型IEnumerable,因为实现泛型版本的所有集合也实现了非泛型版本。IEnumerable是协变的,因此如果您只是
var enumerable = content as IEnumerable<T>;
if (enumerable == null)
DoSomethingWithContent(content);
else
DoSomethingWithContent(enumerable);
var enumerable=内容为IEnumerable;
if(可枚举==null)
dosomethingwhithcontent(content);
其他的
含含量的dosomething(可枚举);
…即使content
的实际运行时类型为IEnumerable
,其中C
继承T
,它仍将调用DoSomethingWithContent(IEnumerable content)
这并不能说明为什么您首先要在
t
中尝试“fit”IEnumerable
HttpResponseMessage Modify(HttpResponseMessage response) {
T content;
if(response.TryGetContentValue<T>(out content)) {
DoSomethingWithContent(content);
}
else
{
IEnumerable<T> content;
if(response.TryGetContentValue<IEnumerable<T>>(out content)) {
DoSomethingWithContent(content);
}
}
return response;
}
HttpResponseMessage修改(HttpResponseMessage响应){
T含量;
if(response.TryGetContentValue(输出内容)){
dosomethingwhithcontent(content);
}
其他的
{
可数内容;
if(response.TryGetContentValue(输出内容)){
dosomethingwhithcontent(content);
}
}
返回响应;
}
假设DoSomething
对于IEnumerable
和T
是一样的(例如,一个委托给另一个)-我认为总是使用IEnumerable
-毕竟,T
只是一个带有1个值的IEnumerable
当然,这避免了TryGetContentValue
只会返回T
——而不是IEnumerable
的问题。您可以先尝试T
,然后返回到IEnumerable
。我认为把它作为一个物体拿出来,自己处理演员也可以
所以-我想你最终会得到这样的结果:
public class MyClass<T> {
HttpResponseMessage Modify(HttpResponseMessage response) {
IEnumerable<T> content = this.GetContent(response);
DoSomethingWithContent(content);
return response;
}
private IEnumerable<T> GetContent(HttpResponseMessage response) {
object content;
if (!response.TryGetContentValue(out content)) return new T[] { };
if (content is T) return new T[] { (T)content };
return content as IEnumerable<T> ?? new T[] { };
}
public void DoSomethingWithContent(IEnumerable<T> content) {
foreach (var t in content) {
// blah, blah
}
}
}
公共类MyClass{
HttpResponseMessage修改(HttpResponseMessage响应){
IEnumerable content=this.GetContent(响应);
dosomethingwhithcontent(content);
返回响应;
}
私有IEnumerable GetContent(HttpResponseMessage响应){
对象内容;
if(!response.TryGetContentValue(out content))返回新的T[]{};
如果(内容为T),则返回新的T[]{(T)内容};
将内容返回为IEnumerable??新的T[]{};
}
公共void DoSomethingWithContent(IEnumerable content){
foreach(内容中的var t){
//废话,废话
}
}
}
如果
DoSomethingWithContent(T)
和DoSomethingWithContent(IEnumerable)
实际上是不同的,那么您基本上应该遵循与GetContent
相同的模式来做出分支决策。您在寻找这个吗@罗伯塔维:我不认为这里发生了什么。好吧,值得一试。一般来说,当我问自己这样的问题时,是因为我没有尽我所能设计好东西。如果你能将代码重构为不需要任何运行时测试,这可能值得一看。@CoryNelson我同意你的观点-首先要让它工作,然后再重构:)事实上,我非常喜欢这个想法。我们来考虑一下这个问题,但是内容声明呢。现在,在尝试获取内容值之前,我有T content
,但DoSomethingWithContent
接受T
或IEnumerable
。将内容声明为对象会导致无法解析方法…,候选对象是…
如果您想声明对象内容
,那么您可以使用T
进行相同的测试和强制转换,正如我在IEnumerable
中所示。问题不是关于IEnumerable
与IEnumerable
的关系。它是关于IEnumerable
vsT
@recursive的,这是as
在运行时测试的内容。谢谢你,马克
HttpResponseMessage Modify(HttpResponseMessage response) {
T content;
if(response.TryGetContentValue<T>(out content)) {
DoSomethingWithContent(content);
}
else
{
IEnumerable<T> content;
if(response.TryGetContentValue<IEnumerable<T>>(out content)) {
DoSomethingWithContent(content);
}
}
return response;
}
public class MyClass<T> {
HttpResponseMessage Modify(HttpResponseMessage response) {
IEnumerable<T> content = this.GetContent(response);
DoSomethingWithContent(content);
return response;
}
private IEnumerable<T> GetContent(HttpResponseMessage response) {
object content;
if (!response.TryGetContentValue(out content)) return new T[] { };
if (content is T) return new T[] { (T)content };
return content as IEnumerable<T> ?? new T[] { };
}
public void DoSomethingWithContent(IEnumerable<T> content) {
foreach (var t in content) {
// blah, blah
}
}
}