函数返回一个generics类型,其值仅在运行时已知

我需要使用如下通用接口:

public interface IContainer { IEnumerable<IContent> Contents { get; } } 

实现此接口的对象由以下generics方法返回:

 IContainer GetContainer(IProperty property); 

直到运行时,类型T才是未知的。

使用reflection我可以调用GetContainer方法并获得结果。

我的问题是我不知道如何枚举具有Object类型的结果(因此我无法将其IEnumerableIEnumerable )。

我也试过如下铸造,但它不起作用(它说“预期类型”):

 var myContainer = genericMethodInfo.Invoke( myService, new object[] { property }) as typeof(IContainer).MakeGenericType(type); 

其中type是运行时类型, myService是公开GetContainer方法的服务, propertyIProperty类型。

更新 :在我的博客中查看我的完整解决方案: http : //stefanoricciardi.com/2010/02/18/generics-with-type-uknown-at-compile-time/

typeof(IContainer <>)。MakeGenericType(type)仅在运行时进行求值,而“as”需要在编译时知道类型。

我真正不明白的是这个评论:我的问题是我不知道如何枚举具有Object类型的结果(因此我无法将其转换为IEnumerable)。

myContainer可能是一个Object但它肯定可以转换为IEnumerable? 如果它不能那么它就不能枚举。

您的类型T必须由编译器知道,因此这不起作用。 您可以尝试制作非通用版本的界面,如下所示:

 public interface IContainer { IEnumerable Contents { get; } } public interface IContainer : IContainer { ... } 

这样你就可以投射并能够使用它了。

首先,在转换时你需要一个类型(double,int); typeof接受一个类型参数并返回一个Type类型的类。

  object x = 0.0; Type t = typeof(double); double y = x as t; //does not compile - t is not a type - it's an instance of type Type double y = x as typeof(double); //same as above double y = x as double; //compiles - double is a type Type z = x as Type; //compiles - Type is a type 

其次,这是一些示例代码:

 using System; using System.Collections.Generic; using System.Collections; using System.Reflection; using System.Diagnostics; namespace TryThis { public interface IContainer { IEnumerable> Contents { get; } } public interface IContent { T GetMyContent(); } public interface IProperty { } public class Content : IContent { T m_content = default(T); public T GetMyContent() { return m_content; } public Content(T val) { m_content = val; } } public class Contents : IEnumerable> { List> m_contents = new List>(); IEnumerator> IEnumerable>.GetEnumerator() { return m_contents.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return m_contents.GetEnumerator(); } public Contents(params T[] contents) { foreach (T item in contents) m_contents.Add(new Content(item)); } } public class TestGenericContent : IContainer { public IContainer GetContainer(IProperty property) { return this; } public IEnumerable> Contents { get { return new Contents(1, 2, 3); } } } public static class TryThisOut { static void Test2(object o) { Type t = o.GetType(); Type tInterface = t.GetInterface("IContainer`1"); //could be null if o does not implement IContainer Type tGenericArg = tInterface.GetGenericArguments()[0]; //extracts T from IContainer MethodInfo info = t.GetMethod("GetContainer"); IProperty propArg = null; //null in this example object oContainer = info.Invoke(o, new object[] { propArg }); PropertyInfo prop = tInterface.GetProperty("Contents"); object oContents = prop.GetGetMethod().Invoke(oContainer, null); //oContents is of type IEnumerable>, which derives from IEnumerable, so we can cast IEnumerable enumeratedContents = oContents as IEnumerable; MethodInfo getContentItem = typeof(IContent<>).MakeGenericType(tGenericArg).GetMethod("GetMyContent"); foreach (object item in enumeratedContents) { object oContentItem = getContentItem.Invoke(item, null); Debug.Print("Item {0} of type {1}", oContentItem, oContentItem.GetType()); //... } } public static void Test() { object o = new TestGenericContent(); Test2(o); } } } 

如果您正在考虑迁移到动态类型提供的.Net 4。

我假设您的对象只会作为有限数量的类型之一返回,那么为什么不在转换之前测试它们,例如,如果object是thisclass?

对不起,如果我误解了,我无法准确理解你的目标是什么。 你在寻找这样的东西吗?

 var myContainer = typeof(ClassWithGetContainer) .GetMethod("GetContainer") .MakeGenericMethod(runtimeType) .Invoke(InstanceOfClassWithGetContainer, new object[] { property });