已解决,请参阅帖子末尾的解决方案。
我有一个返回附件列表的方法。我有三种类型的附件,它们都扩展了一个名为GenericAttachment
的类:
GenericAttachment
||
==> FormA_Attachment
==> FormB_Attachment
==> FormC_Attachment
我也有不同的表单类型,它们都扩展了一个名为GenericForm
的类:
GenericForm
||
==> FormA
==> FormB
==> FormC
该方法必须采用FormA,FormB或FormC的Type
参数,并返回相应类型的附件。
我先试过这个:
public static List<GenericAttachment> GetAllAttachmentsByFormID<T>(int sqlFormId, Type type) where T : GenericForm
{
//this returns e.g. FormA_Attachment based on FormA as the input
Type attachmentType = GetAttachmentTypeByFormType(type);
//Call a generic function (overload of this one)
//that returns all attachments and requires a specific type argument.
//Meanwhile, .Invoke()'s return type is just an `object`
var attachments = typeof(AttachmentManager)
.GetMethod("GetAllAttachmentsByFormID", new[] { typeof(int) }) // select the correct overload for the method
.MakeGenericMethod(attachmentType)
.Invoke(new AttachmentManager(), new object[] { sqlFormId });
return (List<GenericAttachment>)attachments;
}
然而,演员阵容在运行时失败(&#34;未能演员&#34;)。
然后我用if / else语句尝试了一种笨拙的方式,但它没有编译,因为&#34;无法将List<FormA_Attachment>
转换为List<GenericAttachment>
&#34;。尝试使用Convert.ChangeType
和普通演员,如下所示。
它没有编译是很奇怪的,例如, FormA_Attachment
扩展了GenericAttachment
。
if (attachmentType == typeof(FormA_Attachment))
{
return (List<FormA_Attachment>) Convert.ChangeType(attachments, typeof(List<FormA_Attachment>));
}
else if (attachmentType == typeof(FormB_Attachment))
{
return (List<FormB_Attachment>)attachments;
}
else if (attachmentType == typeof(FormC_Attachment))
{
return (List<FormC_Attachment>)attachments;
}
else
{
throw new Exception("Invalid attachment class type.");
}
如何将attachments
转换为动态选择List<type>
的{{1}}?
解决方案:
感谢@Mikhail Neofitov,以下代码有效。
type
的类型为attachments
,因为这是object
返回的内容。
所以我首先将其转换为特定类型,然后使用.Invoke()
转换为不太具体的类型。
.OfType<GenericAttachment>().ToList()
答案 0 :(得分:4)
C#不允许types covariance,这意味着List<string>
无法简单地转换为List<object>
。
在您的情况下,您可以使用LINQ
扩展方法OfType()
,如下所示:
return attachments.OfType<GenericAttachment>().ToList();
我想,您可以修改应用程序体系结构,将结果类型的GenericArgument
传递给GenericForm
的泛型参数,并定义一个抽象方法,用于在结果类型中返回结果附件。此外,您的通用参数<T>
没用,您不在方法体中使用它。
答案 1 :(得分:1)
您可以在此处使用协方差。 List<T>
不是变体,但它实现了IEnumerable<out T>
,它在T中是协变的。这意味着您无法将object
转换为List<GenericAttachment>
,但您可以转换它到IEnumerable<GenericAttachment>
。因此,您应该能够执行以下操作,而不是所有这些if
:
return ((IEnumerable<GenericAttachment>)attachments).ToList();
答案 2 :(得分:0)
看看this。这是将List<Derived>
投射到List<Base>