[TestMethod]
public void TestMyGenericBaseClasses()
{
Type typeCrazy = ThisPartyIsTypeCrazyWOOT();
// How do I create a generic object?
MadnessOhYeah<typeCrazy> sanity = new MadnessOhYeah<typeCrazy>();
// How do I use a generic object after it has been created?
Assert.IsTrue(sanity.MyTrueFunction(), "this is sparta");
// How do I call a generic function generically?
bool result = MyFunction<typeCrazy>();
Assert.IsTrue(result, "I did not get my teeth whitened!");
}
有没有办法让这个编译? (ThisPartyIsTypeCrazyWOOT返回一个Type)因为这是一个测试,我们不关心必须使用反射或任何东西,除非那只是绝对疯狂。
我现在感受到这是不可能的,并且我们的测试功能必须更加具体。
答案 0 :(得分:3)
答案 1 :(得分:2)
更新2 :我发布的第一个示例仍然没有100%回答问题,因为它涉及到List<int>
的强制转换,这是一种已知的类型编译时间。下面是一个仅反射的解决方案,它说明了如何使用泛型类型,而对类型参数本身一无所知。但是,正如你所看到的,它......嗯,恶心;)
Type userType = GetUserSuppliedType();
// Now let's say userType is T.
// Then here we are getting the type typeof(List<T>).
// But, of course, there's no way to have any such information in the code.
Type listOfUserType = typeof(List<>).MakeGenericType(new[] { userType });
// This is effectively calling new List<T>();
object listObject = Activator.CreateInstance(listOfUserType);
// Do you see how messy this is getting?
MethodInfo addMethod = listOfUserType.GetMethod("Add");
// We better hope this matches userType!
object input = GetUserSuppliedInput();
// I suppose we could check it, to be sure...
if (input == null || input.GetType() != userType)
{
throw new InvalidOperationException("That isn't going to work!");
}
// Here we are finally calling List<T>.Add(input) -- just in the most ass-
// backwards way imaginable.
addMethod.Invoke(listObject, new[] { input });
更新:好的,如果您坚持这样做,以下是可能的示例 - 但非常麻烦!
Type genericListType = typeof(List<>);
Type listOfInt32Type = genericListType.MakeGenericType(new[] { typeof(int) });
object listObject = Activator.CreateInstance(listOfInt32Type);
List<int> list = (List<int>)listObject;
list.Add(1);
泛型不能像这样工作,因为Type
对象可能是任何东西。请考虑以下代码:
var list = new List<int>();
list.Add(1);
上述代码中list
的类型为List<int>
,它定义了list
上合法的操作,例如Add(1)
。
现在考虑一下:
Type t = GetTypeFromIndeterminateSourceSuchAsUserInput();
var list = new List<t>();
list.Add(?);
当t
是Type
个对象而不是编译器可以解析的类型的名称(如int
)时,它就是&#39}不太可能使用该类型实例化泛型类型 - 或者更确切地说,可能(参见Andrey's answer),但您无法使用< / em>以任何通用方式生成的对象。
现在,你可能认为这样的事情应该有效:
Type t = typeof(int);
var list = new List<t>();
list.Add(1);
...但仅仅因为t
的值在编译时已知(由你),并不会改变一般情况下的工作方式。
无论如何,是的,可以使用反射;但是,如果你沿着这条道路前进,那么你就会致力于一个反思很重的解决方案。我所得到的是,一般来说,这不是一件特别现实的事情。