我很快在Notepad ++中输入了此信息,因此请原谅任何错别字/错误。如果可能的话,我会摆脱一些重复的工作(例如,长案子声明)。没什么大不了的,但是我很好奇是否有可能,如果可以的话,实际实现代码有多糟糕。
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;}
}
使用此代码,我可以在视图中创建一个节,并为每种类型创建一个类。该类由ORM重用,并从API反序列化。最麻烦的一点是在控制器中有一个case语句,该语句基于“ ApiAndClassName”以正确的类型调用通用方法。我可以编辑ORM,因此它是基于字符串的而不是通用的,但由于各种原因,我不喜欢该方法。我可以将case语句转换为控制器中的集合,也可以仅将其移至服务层,但是我所拥有的已经可以了。我也可以重构,以便从集合中构建视图,但是在其他数据点上,这并不是最佳选择。除非我缺少某些东西,否则字符串事物的通用参数还很有意义。这是一个附带条件的案例……并且有点好奇是否可以做得很好。
答案 0 :(得分:1)
一般来说,强类型代表是您的朋友。编译时类型检查是功能,而不是要打的敌人。如果没有它们或过于激进的转换,我们将从this comic获得JavaScript和PHP示例。
对于使用弱类型语言或WebService的工作,.NET具有ExpandoObject。数据可以存储在其中,然后再传输到适当类型的实例中。同样,您的情况似乎属于JSON反序列化,这是一个完善的代码。
泛型是错误的术语。泛型通常是关于在编译时仍然已知的类型,因此编译时类型检查仍然有效。您明确地知道,类型仅在运行时才在编译时未知。这与泛型非常不同。动态类型是afaik的专有术语。但是不要将其与Dynamic类型混合使用(是的,在这里命名确实很混乱)。
Reflection是您要查找的机器人。对于大多数目的,类或字段的名称在运行时不存在。它主要是供您和编译器进行通信的。现在反射是一个例外。这是关于根据事物名称的字符串表示来获取事物(例如实例或属性/字段)的全部方法。必要的元数据与COM支持一样都包含在.NET程序集中。但是由于我支持强类型化,所以我不是它的朋友。
switch / case语句通常可以替换为某种类型的集合。案例实际上只是检查常量集合的一种硬编码方式。您可以使用案例标识符作为键,还可以使用其他任何值。您可以完全使用函数作为值(感谢委托)。或使用Type类型,然后用于实例创建。
但是对于您而言,这听起来似乎是错误的。继承标准-继承可能是您要查找的 real 机器人。 JSON服务通常不会在单个集合中为您提供其他实例,除非这些实例以某种方式相关。 “ SomeClassName”和“ AnotherClass”应该有另一个祖先。或者实际上,它们甚至应该只是一个类-QueryType只是该类的字符串字段。
答案 1 :(得分:0)
假设您有一种将字符串映射到Type
对象的方法,可以:可以使用MethodInfo.MakeGenericMethod()
:
var totalCount = (int) (
GetType()
.GetMethod("GetTotalCount")
.MakeGenericMethod(MapStringToType(s.QueryType))
.Invoke(this, null)
);
这假定在本地范围内存在方法Type MapStringToType(string)
。
映射类型的一种方法是使用Dictionary<string, Type>
并用允许的类型及其各自的名称填充,这些名称及其相应名称将在JSON数据中用于引用它们。