泛型将未知类型转换为另一种类型

时间:2013-01-05 17:31:54

标签: c# visual-studio-2010 generics

我将我的问题改写为更具体,并针对实际关注的领域。

我有许多不同的类是我的实体,我不在那个类中。当我想将实体升级到新实体时,我想将属性转移到被称为相同的新属性(并且我发现它们不区分大小写)。

我的问题很简单,但可能需要一个复杂的答案。

当我遇到与升级版本不同的类型时,我需要将旧版本转换为新版本。这两种类型都是未知的,因为这就是重点。我可以通过我想要的任何两个类,它将传输属性。

所以,如果我有两个班级:

public class OldEntity
{
    public string Name {get;set;}
    public int SomeProperty {get;set;}
}

public class NewEntity
{
    public string Name {get;set;}
    public string SomeProperty {get;set;}
}

所以我需要找出旧版SomeProperty的内容,然后将其转换为SomeProperty的新类型。

我认为我能做什么,我希望有更通用的方法:

switch (typeof(SomeProperty.Value.GetType())
{
    case typeof(Int):
        return Int.Parse(OldSomeProperty.Value);
}

显然这是非常原始的代码,但你得到了要点。

请有人可以给我一个更通用的方法吗,还有一件事是我已经下载了AutoMapper,它没有评论,所以如果有人能告诉我它在哪里以及如何做到这将是一个很好的答案

所以我尝试过简单的解决方法,而不是非常通用:

public static object ConvertSourceObjectDestinationObject(object source, object destination)
{
    // get the string representation of the source object
    var strRepresentation = source.ToString();
    // find out the destinations type
    var originalCode = AssemblyCode(destination.GetType().Assembly.ToString());

    // search for a match then convert the source object to the new destination objects type
    switch (originalCode)
    {
        case 0:
            return strRepresentation;
        case 1:
            return int.Parse(strRepresentation);
        case 2:
            return decimal.Parse(strRepresentation);
        case 3:
            return DateTime.Parse(strRepresentation);
        case 4:
            return byte.Parse(strRepresentation);
        case 5:
            return float.Parse(strRepresentation);
        case 6:
            return Guid.Parse(strRepresentation);
        default:
            return strRepresentation;
    }
}

public static int AssemblyCode(string assemblyString)
{
    if (assemblyString.Equals(typeof(string).Assembly.ToString()))
        return 0;

    if (assemblyString.Equals(typeof(int).Assembly.ToString()))
        return 1;

    if (assemblyString.Equals(typeof(decimal).Assembly.ToString()))
        return 2;

    if (assemblyString.Equals(typeof(DateTime).Assembly.ToString()))
        return 3;

    if (assemblyString.Equals(typeof(byte).Assembly.ToString()))
        return 4;

    if (assemblyString.Equals(typeof(float).Assembly.ToString()))
        return 5;

    if (assemblyString.Equals(typeof(Guid).Assembly.ToString()))
        return 6;

    return -1;
}

我做了一个新的,它使用TryParse而不是Parse来使它更安全,但你得到了要点。我知道它并不优雅,但是如果有人能够让我知道如何将未知物体正确地投射到其他未知物体上那将会很棒。

2 个答案:

答案 0 :(得分:1)

通用系统需要一些帮助,知道有时泛型的类型。这是通过类型约束(ref)来处理的,它可以帮助您完成示例。

如果您知道要转换的泛型类型始终是某个基类,请使用where T:<base class name>约束。

如果强制转换异常是由于它没有识别未继承的类型之间的隐式转换,那么反射可能只是你的选择。

答案 1 :(得分:0)

您使用通用约束new

 public static void SetEntityValue<TEntity>(ref TEntity entityToTransform, PropertyHelper entityProperty) where TEntity: new

允许你这样做:

TEntity ent = new TEntity()

OR(我想这就是你想要的)

使用相同的东西(泛型约束),你可以告诉方法泛型参数类型是什么/派生出来的。

public static void SetEntityValue<TEntity>(ref TEntity entityToTransform, PropertyHelper entityProperty) where TEntity: x

这基本上意味着你可以告诉编译器泛型类型必须是什么(这意味着你的方法中的强制转换是有意义的并且编译

如果您不知道该类型是什么,那么您可能会在对象上使用反射......