簡體   English   中英

泛型將未知類型轉換為另一個

[英]Generics casting an unknown type to another

我將我的問題改寫為更具體,並針對實際關注的領域。

我有許多不同的類,它們是我的實體,但我沒有那個類。 當我想將實體升級到新的實體時,我想將屬性轉移到稱為相同的新實體上(並且我發現它們不區分大小寫)。

我的問題很簡單,但可能需要一個復雜的答案。

當我遇到一種與升級版不同的類型時,我需要將舊版轉換為新版。 這兩種類型都是未知的,因為那就是重點。 我可以通過任何兩個我想要的類,它將很好地傳遞屬性。

因此,如果我有兩節課:

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來使其更安全,但是您的要點是。 我知道這不是很優雅,但是如果有人可以讓我了解如何正確地將未知對象投射到其他未知對象,那就太好了。

泛型系統需要一些幫助,這有時會知道泛型是什么類型。 這是通過類型約束( ref )來解決的,它可能會對您的示例有所幫助。

如果知道要轉換的泛型類型始終是某些基類,請使用where T:<base class name>約束。

如果強制轉換異常是由於它無法識別未繼承的類型之間的隱式強制轉換,則反射可能是您唯一的選擇。

您使用通用約束new

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

這將使您能夠:

TEntity ent = new TEntity()

或(我認為這是您想要的)

使用相同的東西(通用約束),您可以告訴方法通用參數類型是從/派生的。

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

這基本上意味着您可以告訴編譯器泛型類型必須是什么(這意味着您在方法中進行的強制轉換將很有意義並可以進行編譯

如果您不知道類型將是什么,那么您可能會喜歡在對象上使用反射...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM