我想测试一个给定的object
是否可以转换为给定的Type
。
在这种情况下,我有一个对象,而Type
代表我想要将它投射到的类型:
public function FooBar(..., object data, Type expected) {
...
var unboxedData = ?
if (unboxedData == null) {
....
}
...
}
如何将data
投射到type
代表的类型?
基本上,我想这样做:
var unboxedData = data as Type;
...但当然您不能将Type
与as
声明一起使用,那么我该怎么办?
答案 0 :(得分:6)
编辑2:我会说没有反思或泛型,这是不可能的。使用反射,您没有编译时检查,必须使用反射(或dynamic
)来进一步调用对象的方法/属性。使用泛型,您不能使用Type对象单独使用。随便挑选。是否可以重构您的调用代码以允许泛型?
如果允许,可以使用通用方法更轻松地处理:
public resultType FooBar<T>(..., object data) {
...
T unboxedData = (T)data;
...
}
修改:如果您包含data as T
的通用类型约束,则可以使用where T : class
:
public something FooBar<T>(..., object data)
where T : class
{
...
T unboxedData = data as T;
if (unboxedData == null) {
...
}
...
}
答案 1 :(得分:3)
...但当然你不能使用带有as语句的Type,所以我该怎么办?
Morre重要的是,你不能以这种方式使用var
。所以这里没有什么可以获得的。
如果是正确的
类型,您可以测试 if (expected.IsInstanceOfType(data))
但是你仍然无法编写任何合适的代码来访问data
上的属性或方法。
答案 2 :(得分:2)
C#快速提供as关键字 在运行时确定给定类型是否与另一个类型兼容。使用as关键字时,可以通过检查null返回值来确定兼容性。请考虑以下事项:
Hexagon hex2 = frank as Hexagon;
if (hex2 == null)
Console.WriteLine("Sorry, frank is not a Hexagon...");
除了as关键字之外,C#语言还提供了is关键字来确定两个项是否兼容。但是,与as关键字不同,如果类型不兼容,则is关键字返回false,而不是null引用。
if (emp is SalesPerson)
{
Console.WriteLine("{0} made {1} sale(s)!", emp.Name,
((SalesPerson)emp).SalesNumber);
}
答案 3 :(得分:1)
if (data.GetType() == t || data.GetType().IsSubclassOf(t))
{
//do your thing
}
应该告诉你它是否完全或是它的子类(因此它可以被投入其中)。
答案 4 :(得分:1)
这非常棘手。问题是var
并不代表“变体”。一旦可以从表达式推断出类型信息,它就更像是临时占位符,C#用实际类型填充。 unboxedData
仍然是一个强类型变量。它只是编译器试图找出类型而不是你明确指定它。值得注意的是,键入仍然在编译时发生,而不是运行时。
如果要在运行时动态转换对象,则无法使用var
或任何其他具体类型说明符。
您的选择仅限于两种可能的声明之一:
根据我想要用unboxedData
做的想法,我怀疑dynamic
是你要去的路线,因为它可以让你调用任何方法目标Type
。
所以这就是我想出来的。
public void FooBar(object value, Type expected)
{
dynamic unboxedData = expected.FromObject(value);
unboxedData.CallSomeMethodDefinedInTheTargetType(); // This will work.
}
这需要以下扩展方法。
public static class TypeExtension
{
public static object FromObject(this Type target, object value)
{
var convertable = value as IConvertible;
if (convertable != null)
{
return convertable.ToType(target, null);
}
Type type = value.GetType();
if (target.IsAssignableFrom(type))
{
return value;
}
MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
foreach (MethodInfo mi in methods)
{
if (mi.ReturnType == target)
{
try
{
return mi.Invoke(null, new object[] { value });
}
catch (TargetInvocationException caught)
{
if (caught.InnerException != null)
{
throw caught.InnerException;
}
throw;
}
}
}
throw new InvalidCastException();
}
}
如果满足下列条件之一,演员阵容将有效。
IConvertible
并具有指向目标类型的转换路径。答案 5 :(得分:0)
好吧,环顾四周我发现了什么... How to check if implicit or explicit cast exists?
要小心,我没有给它太多的测试,但一眼就看出它很有希望。一个很大的负面因素是,如果它无法转换,它会抛出异常:
static bool isConvertableTo(object o, Type t)
{
try
{
var expr = Expression.Constant(o);
var res = Expression.Convert(expr, t);
return true;
}
catch { }
return false;
}
使用相同方法的另一个有用链接:Checking if a type supports an implicit or explicit type conversion to another type with .NET