具有匿名类型作为泛型参数的Generic Type实例,如何正确转换回原始类型?

时间:2014-12-22 06:11:26

标签: c# generics casting

当我需要在我的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. 为什么要使用从非通用接口派生的模板类
  4. 我想说代码已经存在,我无法改变它(至少目前)

    我想做的是:

    1. 检查该接口是否是从ITestInterface
    2. 派生的某个类的实例
    3. 如果是,我需要转换回该类型,可以验证其成员数据
    4. 所以请根据这种情况分享一些解决方案/想法。

      顺便说一句,

      当然我知道我正在使用&#34; Object&#34;在我的最后一个声明转换回类型是不好(或明显错误),但实际上我不知道我可以在这里放哪些其他东西。 &#34;对象&#34;只是一个直观的尝试。请分享任何财产方式来处理这种情况(可能不仅仅是用来取代&#34;对象&#34;)。

1 个答案:

答案 0 :(得分:0)

我不是说这不是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);