我正在尝试在运行时创建一个通用对象。到目前为止,我已经能够创建它,但我无法弄清楚如何投射它。我所拥有的是枚举对象,我想生成EnumMapper,它将枚举值转换为自定义字符串以映射到旧数据库。
Type enumType = myEnum.GetType();
Type enumMapperType = typeof(EnumMapper<>)
.GetGenericTypeDefinition().MakeGenericType(enumType);
var mapper = Activator.CreateInstance(enumMapperType); // OK
EnumMapper<> mapper = (EnumMapper<>) Activator.CreateInstance(enumMapperType); // Error
当我在调试器中检查对象时,它是按照我的预期创建的,但是如何将其转换为可以使用它呢?
班级:
public class EnumMapper<T> : IEnumMapper<T>
界面:
public interface IEnumMapper<T>
{
T EnumValue(string value);
bool HasEnumValue(string stringValue);
bool HasStringValue(T enumValue);
string StringValue(T enumValue);
}
Error 2 ; expected \EnumMapperTest.cs 36
Error 4 ; expected \EnumMapperTest.cs 36
Error 1 Invalid expression term '>' \EnumMapperTest.cs 36
Error 3 Invalid expression term '>' \EnumMapperTest.cs 36
Error 34 Only assignment, call, increment, decrement, and new object expressions can be used as a statement \EnumMapperTest.cs 36
Error 36 The name 'mapper' does not exist in the current context \EnumMapperTest.cs 36
Error 35 Using the generic type 'EnumMapper<T>' requires 1 type arguments \EnumMapperTest.cs 36
Error 37 Using the generic type 'EnumMapper<T>' requires 1 type arguments \EnumMapperTest.cs 36
答案 0 :(得分:2)
据我所知,C#中无法提供您需要的确切内容。基本上,您需要一个方法来拥有不同类型或返回的变量,基于常规非泛型参数的值,即参数是typeof(Enum1)
,而结果变量是{{1}如果参数为EnumMapper<Enum1>
,则结果变量为typeof(Enum2)
。
您可以使用泛型参数执行此操作,但是,由于泛型是关于编译时信息的,并且您在运行时只有值,因此在这种情况下不能使用它们。
你能做什么(以及我所做的)是使用动态代码解决这个问题,小心尽快进入静态类型的土地(动态是真的具有传染性,有些人说像微笑,有人说像病毒一样):
EnumMapper<Enum2>
调用代码如:
public dynamic GetMapperObject(Type enumType)
{
Type enumMapperType = typeof(EnumMapper<>)
.GetGenericTypeDefinition()
.MakeGenericType(enumType);
var mapper = Activator.CreateInstance(enumMapperType);
return mapper;
}
(旧答案,只是为问题增加了另一层次的间接性:))
你可以用通用方法包装所有这些,如下所示:
var mapper = GetMapperObject(enumType);
//dynamic call, bind the resut to a statically typed variable
bool result = mapper.HasEnumValue("SomeStringValue")
并使用
调用它public EnumMapper<T> GetMapperObject<T>()
{
Type enumType = typeof(T);
Type enumMapperType = typeof(EnumMapper<>)
.GetGenericTypeDefinition()
.MakeGenericType(enumType);
var mapper = Activator.CreateInstance(enumMapperType);
return mapper as EnumMapper<T>;
}
但是,如果枚举只有一个值,则可以使用类型推断,例如:
var mapper = GetMapperObject<EnumMapperTestEnum>();
并使用类型推断来调用它
//everything is the same, just different signature
public EnumMapper<T> GetMapperByExample<T>(T item)
{
Type enumType = typeof(T);
Type enumMapperType = typeof(EnumMapper<>)
.GetGenericTypeDefinition()
.MakeGenericType(enumType);
var mapper = Activator.CreateInstance(enumMapperType); // OK
return mapper as EnumMapper<T>;
}