簡體   English   中英

有沒有辦法從字符串派生類型參數以傳遞給泛型方法?

[英]Is there a way to derive a type argument from a string for passing into a generic method?

我在記事本++中快速輸入了這個,所以請原諒任何錯別字/錯誤。 如果可能的話,我會擺脫一些重復的工作(即長案例陳述)。 沒什么大不了的,但我很好奇它是否可能,如果可能的話,實際實現代碼會有多糟糕。

jsonFromWebpage = {
    StatusUpdate: {
        QueryType: "SomeClassName",
        LocalCount: 5,
        RemoteCount: 5
    },
    StatusUpdate: {
        QueryType: "AnotherClass",
        LocalCount: 29,
        RemoteCount: 30
    }
}

// Model
public class StatusUpdate
{
    public string QueryType { get; set; }
    public int LocalCount { get; set; }
    public int RemoteCount { get; set; }
}

// Controller
public IActionResult GetStatusUpdate([FromBody] List<StatusUpdate> status)
{
    _service.GetStatusUpdate(status);
    return status
}

// Service
public List<Status> GetStatusUpdate(List<StatusUpdate> status)
{
    foreach(var s in status)
    {
        var typeArgument = s.QueryType; // <--- Is there a way for this...
        status.CurrentCount = GetTotalCount<typeArgument>(); // <--- to work here?
        status.RemoteCount = thisworksfineforotherreasons(s.QueryType);
    }
}

// Repo
public int GetTotalCount<T>() where T: class
{
    var result = _db.GetCount<T>();
    return result;
}

編輯

首先,感謝所有回復的人。 到目前為止,我已經閱讀了所有內容,我想提供更多背景信息。 這是對示例的不同看法:

// View
<div class="col-12">
    <div class="api-types">History</div>
    <div class="progress-bar">50 out of 50 copied</div>
</div>
<div class="col-12">
    <div class="api-types">Users</div>
    <div class="progress-bar">25 out of 32 copied</div>
</div>

// -- View javascript

var types = [];
$(".api-types").each(function (c, i) {
    types.push({ ApiAndClassName: $(i).text() });
});

pushToController(JSON.stringify(types));

// Controller
public IActionResult GetSyncStatus(List<SyncStatusVM> status)
{
    _service.GetSyncStatus(status);
    return Json(status);
}

// Service
public List<SyncStatusVM> GetSyncStatus(List<SyncStatusVM> status)
{
    foreach(var s in status)
    {
        // LocalCount
        var magicTypeFigurator = s.ApiAndClassName
        s.LocalCount = _repo.GetCount<magicTypeFigurator>(); <-- "this is a variable but should be a type..."

        // Remote
        var url = $"https://api.domain.com/{s.ApiAndClassName.ToLower()}"
        s.RemoteCount = FetchCountFromApi(url);
    }
    return status;
}

// Repository
public long GetCount<T>()
{
    var result = _orm.Count<T>();
    return result;
}

// Models
public class SyncStatusVM
{
    public string ApiAndClassName { get; set; }
    public int LocalCount { get; set; }
    public int RemoteCount { get; set; }
}

public class History
{
    public long Id {get;set;}
    public DateTime CreatedDate {get;set;}
    public string Message {get;set;}
}

public class Users
{
    public long Id {get;set;}
    public string FirstName {get;set;}
    public string LastName {get;set;}
}

使用此代碼,我可以在視圖中創建一個部分,並為每種類型創建一個 class。 class 被 ORM 重用,並從 API 反序列化。 最麻煩的一點是在 controller 中有一個 case 語句,它基於“ApiAndClassName”調用具有正確類型的泛型方法。 我可以編輯 ORM 所以它是基於字符串的而不是通用的,但由於各種原因我不喜歡這種方法。 我可以將 case 語句轉換為 controller 中的集合,或者只是將其移動到服務層,但我所擁有的已經有效。 我也可以重構,以便從集合構建視圖,但還有其他數據點不是最佳選擇。 除非我缺少某些東西,否則字符串事物的通用參數是有道理的。 這是一個邊緣案例......有點好奇它是否可以做得足夠好。

一般來說,強類型化是你的朋友。 編譯時類型檢查是一項功能,而不是要戰斗的敵人。 沒有它們或過於激進的鑄造,我們從這部漫畫中得到 JavaScript 和 PHP 示例。

對於弱類型語言或 WebServices,.NET 具有 ExpandoObject。 數據可以存儲在其中,然后傳輸到適當類型的實例中。 此外,您的案例似乎會落入 JSON 反序列化,這是一個完善的代碼。

通用是錯誤的術語。 Generics 通常是關於在編譯時仍然已知的類型,因此編譯時類型檢查仍然有效。 您明確表示在編譯時不知道該類型,僅在運行時才知道。 這與泛型非常不同。 動態類型是正確的術語 afaik。 但是不要將它與 Dynamic 類型混淆(是的,這里的命名變得非常混亂)。

反射是您正在尋找的機器人。 對於大多數用途,運行時不存在 class 或字段的名稱。 它主要是供您和編譯器進行通信的。 現在反射是個例外。 這一切都是關於根據名稱的字符串表示來獲取東西(如實例或屬性/字段)。 必要的元數據被烘焙到 .NET 程序集中,與 COM 支持一樣多。 但由於我支持強類型化,我不是它的朋友。

switch/case 語句通常可以替換為某種集合。 案例實際上只是檢查常量集合的硬編碼方式。 您使用案例標識符作為鍵以及值所需的任何其他內容。 您完全可以使用 Functions 作為值(感謝委托)。 Type類型,然后用於創建實例。

但是對於您的情況,聽起來所有這些都是錯誤的。 沼澤標准 Inheritance - Inheritance 可能是您正在尋找的真正機器人。 JSON 服務通常不會在單個集合中為您提供不同的實例,除非這些實例以某種方式相關。 “SomeClassName”和“AnotherClass”應該有另一個祖先。 或者實際上,它們甚至應該只是一個 class - QueryType 只是所說 class 的字符串字段。

假設您有辦法將 map 字符串轉換為Type對象,是的:您可以使用MethodInfo.MakeGenericMethod()

var totalCount = (int) (
    GetType()
    .GetMethod("GetTotalCount")
    .MakeGenericMethod(MapStringToType(s.QueryType))
    .Invoke(this, null)
);

這假設在本地 scope 中存在方法Type MapStringToType(string)

map 類型的一種方法是使用Dictionary<string, Type>並用允許的類型及其各自的名稱填充它,這些名稱將在 JSON 數據中用於引用它們。

暫無
暫無

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

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