以匿名类型作为泛型参数的泛型类型实例,如何正确转换回原始类型
本文关键字:类型 实例 何正确 转换 原始 泛型类型 参数 泛型 | 更新日期: 2023-09-27 18:34:50
当我需要验证UT中的某些代码路径时,我会遇到此问题。
我需要转换回其原始类型以验证数据字段是否已正确设置。
我抽象了类定义,我的UT现在在这个例子的主函数中
public interface ITestInterface { };
public class TestClass<T> : ITestInterface
{
public T member { get; set; }
}
public static class Util
{
public static ITestInterface Create<C>(C t)
{
return new TestClass<C> { member = t };
}
public static ITestInterface CreateInstance()
{
return Create(new
{
p1 = 100,
p2 = "string"
});
}
}
class Program
{
static void Main(string[] args)
{
var a = Util.CreateInstance();
var b = a as TestClass<Object>;
// this will be "null" in this example
// So, how can I convert back to its real type?
// And get the "member" data
}
}
我认为这个例子可以准确地解释我的问题和我想要什么
请多耐心等待:
- 为什么使用匿名类型
- 为什么使用界面
- 为什么使用从非泛型接口派生的模板类
我想说代码已经存在,我无法更改它(至少目前(
我想做的是:
- 检查该接口是否是从
ITestInterface
派生的某个类的实例 - 如果是,我需要转换回该类型,可以验证其成员数据
因此,请根据此场景分享一些解决方案/想法。
顺便说一句,
当然,我知道我在上一条语句中使用"Object"转换回类型不好(或明显错误(,但实际上我不知道我可以在这里放哪些其他东西。"对象"只是一个直观的尝试。请分享处理这种情况的任何属性方法(可能不仅仅是用于替换"对象"的东西(。
我并不是说这不是XY问题,而是回答你提出的问题。
如果与匿名类型位于同一作用域中,则可以对泛型使用类型推断,将其强制转换为匿名类型。
在下面的示例中,我在调用 Util.Create 之前创建了匿名类型的项,以便我在变量中有一个该类型的实例,以便以后可以使用。 然后我调用泛型方法 GetAsTestClass<T>
,它使用基于第二个参数的类型推断将 T 设置为匿名类型。 然后它返回 item as TestClass<T>
,其中 T 是您的匿名类型。
public void TestMethod1()
{
var anonItem = new
{
p1 = 100,
p2 = "string"
};
var a = Util.Create(anonItem);
var b = GetAsTestClass(a, anonItem);
// this will be "null" in this example
// So, how can I convert back to its real type?
// And get the "member" data
var c = b.member;
Assert.AreEqual(100, c.p1);
}
public TestClass<T> GetAsTestClass<T>(ITestInterface item, T silentType)
{
return item as TestClass<T>;
}
编辑:
您的特定要求似乎排除了类型安全选项。 下面是使用非类型安全反射和动态方法的代码示例。 请注意,要使动态版本正常工作,您需要在项目中引用 Microsoft.CSharp。
var a = Util.Create(new
{
p1 = 100,
p2 = "string"
});
var memberAnon = a
.GetType()
.GetProperty("member")
.GetValue(a);
var p1 = memberAnon
.GetType()
.GetProperty("p1")
.GetValue(memberAnon);
Assert.AreEqual(100, p1);
或动态方式
dynamic dynamicVar = a;
Assert.AreEqual(100, dynamicVar.member.p1);