c# - C# 方法调用无法将实现接口的类转换为所述接口
问题描述
所以我有一个应用程序将 websocket 请求发送到服务器并记录响应以供以后查看。我希望用户能够检查他们想要记录的响应。我有获取所有不同响应类型的方法,并且每种响应类型都实现了 IWebSocketResponseData。然后我有一个方法,它根据传入的 CheckBoxData 列表返回所有响应类型,它获取从服务器检查的所有响应,并且应该返回 List<IWebSocketResponseData>。
public async Task<List<IWebSocketResponseData>> GetData(List<CheckBoxData> dataToGet)
{
var toReturn = new List<IWebSocketResponseData>();
foreach (var data in dataToGet)
{
var method = GetType()
.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
.SingleOrDefault(m => m.ReturnType.GenericTypeArguments.Contains(data.ResponseType));
IWebSocketResponseData response = await (Task<IWebSocketResponseData>)method.Invoke(this, null);
toReturn.Add(response);
}
return toReturn;
}
public async Task<ModuleInfoResponse> GetModuleInfo()
{
await SendAsync(JsonConvert.SerializeObject(new
{
type = "fetch",
item = "modinfo"
}));
return await ReceiveAsync<ModuleInfoResponse>();
}
public async Task<NetworkSettingsResponse> GetNetworkSettings()
{
await SendAsync(JsonConvert.SerializeObject(new
{
type = "fetch",
item = "network"
}));
return await ReceiveAsync<NetworkSettingsResponse>();
}
GetData 下面的两个方法是将从 GetData 方法调用的方法的示例。请记住 ModuleInfoResponse 和 NetworkSettingsResponse 都实现 IWebSocketDataResponse 这基本上只是一个标签,即
public interface IWebSocketDataResponse { }
这给了我一个 InvalidCastException 试图从任何具体的响应类(即 ModuleInfoResponse、NetworkSettingsResponse ......为什么?
编辑:我意识到方法没有空检查,因为我知道我会为此得到一些热量
解决方案
这是因为Task
不是协变的。在 C#中, variance只能应用于泛型接口(和委托),因此您可以执行以下操作:
public interface IWebSocketDataResponse { }
public class ModuleInfoResponse : IWebSocketDataResponse { }
interface IFoo<out T> // or just interface IFoo<out T> {} for testing purposes
{
T GetSomething();
// The following statement generates a compiler error.
// void SetSomething(T sampleArg);
}
IFoo<ModuleInfoResponse> iX = ...;
IFoo<IWebSocketDataResponse> IXX = iX;
但不能:
Task<IWebSocketDataResponse> x = Task.FromResult<ModuleInfoResponse>(null);
另请阅读此答案。
UPD
一种选择是继续使用反射,如下所示:
var task = (Task)method.Invoke(this, null);
await task;
var response = (IWebSocketResponseData)task.GetType().GetProperty("Result").GetValue(task);
推荐阅读
- html - Refreshig 带有 html 代码的 IP 摄像机图像代码仅在本地工作
- python - Python 检查 listelement 是否在值中,但返回它找到的 listelement 而不是 true
- javascript - 如果用户中断,自动向下滚动取消
- python - 基于一个共同的项目运行两个烧瓶应用程序
- java - 我如何调用这些方法?
- javascript - bcrypt.compare() 或 bcrypt.compareSync()
- python - 如何使用带有 preprocessing_function 的数据生成器正确加载图像?
- python - Telethon,给定要更改的单词,更改文本实体的偏移量和长度
- kotlin - 将对象变量公开为公共使其成员无法解析
- rest - 不同 HTTP 方法的目的?