尝试将 C# 匿名类型转换为强类型

Trying to convert an C# anonymous type to a strong type

我正在尝试将一些匿名类型转换回其原始的强类型 class。

我有一些遗留代码(我无法触及)创建匿名 class:


public class Cat : FooId
{
    public int Id { get; set; }
    public string Name { get; set; }
}

var result = new
{
    Id = Mapper.Map<TFooId>(someCat)
};

NOTE: I've tried to make this fake class and interface similar to my code.

然后这给了我:

从这里开始,我不确定如何将其转换回 MyProject.Cat 实例?

我试过(但失败了):

但都失败了。 dynamic 不会引发错误...但我无法访问其中的任何属性。

C# 是一种静态类型语言,这两种类型之间没有任何关系。除非您能够修改定义这些类型的代码,否则从一种类型转换为另一种类型的方法是创建目标类型的新实例并从源对象填充它。

例如:

var resultCat = new Cat { Id = result.Id };

编辑: 从评论看来 result 对象上的 Id 属性 可能是一个实例Cat 或其他一些对象?您将需要进行一些调试以找出您的类型。

但总体概念并没有真正改变。如果您的结果中 Cat 的实例,那么您可以使用该实例。如果您那么为了创建一个您需要创建一个新实例并用您拥有的数据填充它。即使两种类型在直观上或语义上相似,它们也是不同的类型。

David 所说的 C# 是一种静态类型语言,新实例应该按照他建议的方式从源中填充。

但是,有一些解决方法(虽然性能较低),例如反射。

假设您有一个控制台应用程序,您在其中定义了 ObjectExtensions 如下:

public static class ObjectExtensions
{
    public static TOut Map<TOut>(this object @in)
        where TOut : new()
    {
        TOut @out = new TOut();

        if (@in?.GetType() is Type tin)
        {
            Type tout = typeof(TOut);

            foreach ((PropertyInfo pout, PropertyInfo pin) in tout.GetProperties().Join(tin.GetProperties(), pi => pi.Name, pi => pi.Name, (pout, pin) => (pout, pin)))
            {
                pout.SetValue(@out, pin.GetValue(@in));
            }
        }

        return @out;
    }
}

Class1如下:

public class Class1
{
    public string A { get; set; } = "A";
    public string B { get; set; } = "B";
    public string C { get; set; } = "C";

    public override string ToString()
    {
        return $"{{A={A}, B={B}, C={C}}}";
    }
}

您将能够像这样将您的匿名类型映射回其原始的强类型 class:

Console.WriteLine(new { A = "Anonymous A", B = "Anonymous B", C = "Anonymous C" }.Map<Class1>());

因此上面的 bloc 应该显示以下输出:

{A=Anonymous A, B=Anonymous B, C=Anonymous C}

在这种情况下,当然,我假设 Class1(在您的示例中为 Cat)必须有一个 public 无参数构造函数。情况可能并非总是如此。当然还有更复杂的场景,可能涉及其他创建对象的技术,例如克隆或依赖注入。只是说你的想法是可以的。