以匿名类型作为泛型参数的泛型类型实例,如何正确转换回原始类型

本文关键字:类型 实例 何正确 转换 原始 泛型类型 参数 泛型 | 更新日期: 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
    }
}

我认为这个例子可以准确地解释我的问题和我想要什么

请多耐心等待:

  1. 为什么使用匿名类型
  2. 为什么使用界面
  3. 为什么使用从非泛型接口派生的模板类

我想说代码已经存在,我无法更改它(至少目前(

我想做的是:

  1. 检查该接口是否是从ITestInterface派生的某个类的实例
  2. 如果是,我需要转换回该类型,可以验证其成员数据

因此,请根据此场景分享一些解决方案/想法。

顺便说一句,

当然,我知道我在上一条语句中使用"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);