[英]How do I add a derived object to a collection of objects which inherit from the same interface, but use generics?
我對 C# 中的 generics 有點陌生。 我有一個IResult
接口,它具有以下屬性:
public interface IResult<T>
{
string ResultMessage { get; set; }
T Data { get; set; }
}
目的是繼承對象將返回帶有有效負載的字符串消息到 UI。 這將通過另一個 object 傳遞,該 object 具有詳細信息並處理序列化/反序列化,其中將包含這些對象的IEnumerable
。 但是,它需要保存任何 IResult,因為一個 object 中可能有多種類型。 它還必須只在該集合中保存 IResults。 這是旨在包含它們的屬性:
public IEnumerable<IResult<dynamic>> Results { get; set; }
問題是,使用IEnumerable.Cast()
進行強制轉換或顯式內聯強制轉換不起作用。 這里dynamic
的存在只是我在對object
做了同樣的事情之后的一次嘗試,然后演員陣容也失敗了。
我怎樣才能讓更大的有效負載 object 接受IResult<T>
的集合,因為這些都不起作用(首先是因為 T 在上下文中未定義?)
IEnumerable<IResult<T>> Results { get; set; }
//doesn't work as T is undefined, and if defined at the payload level, would result in a single type
IEnumerable<IResult<dynamic>> Results { get; set; }
//doesn't work, the cast fails
IEnumerable<IResult<object>> Results { get; set; }
//doesnt work, the cast fails
無論如何,您要實現的目標與 generics 無關。 重要的是要了解默認情況下 generics 是不變的,例如:
IInterface<One> != IInterface<Two>
即使Two: One
。
你可以在這里閱讀更多關於它的信息
實現您想要的最簡單的方法之一是使用對象
public interface IResult
{
string ResultMessage { get; set; }
object Data { get; set; }
}
但是,如果您想堅持使用 generics,您可以將IResult
接口定義為協變的:
public interface IResult<out T>
{
string ResultMessage { get; set; }
T Data { get; } // note that you cannot specify setter in this case
}
然后,像這樣定義您的 Result 類:
public class ObjectResult: IResult<object>
{
private readonly object _data;
public ObjectResult(object data)
{
_data = data;
}
public string ResultMessage { get; set; }
public object Data => _data;
}
public class StringResult : IResult<string>
{
private readonly string _data;
public StringResult(string data)
{
_data = data;
}
public string ResultMessage { get; set; }
public string Data => _data;
}
現在你可以 go:
IResult<string> stringResult = new StringResult("string");
IResult<object> objectResult = new ObjectResult(new object());
objectResult = stringResult;
Console.WriteLine(objectResult.Data); // prints "string"
老實說,我不認為你可以這樣做。 我能想到的唯一方法是擁有 IResult 實現的接口的非通用版本。 如果您需要 data 屬性,那么您可以像這樣設置它:
public interface IResult
{
string ResultMessage { get; set; }
object DataObject { get; }
}
public interface IResult<T> : IResult
{
T Data { get; set; }
}
public class SomeResult<T> : IResult<T>
{
public string ResultMessage { get; set; }
public T Data { get; set; }
public object DataObject => Data == null ? null : (object)Data;
}
然后,您將擁有一個 IEnumerable,您可以循環並獲取數據。 您甚至可以做一些技巧,讓每個實現都以某種方式對其進行格式化,但這就是我的處理方式。
此外,您可以在此處使用動態而不是 object,但我不完全確定您的最終目標是什么。
在這里試圖提供建設性的批評:你為什么要把這兩個東西強行放在一個界面中? 你不能用 C# 中的類做多個 inheritance,但你可以用接口做。
在閱讀您的問題時,您的 state:
目的是繼承對象將返回帶有有效負載的字符串消息到 UI。
所以,這是一個 function,然后
這將通過另一個 object 提供,它具有詳細信息並處理序列化/反序列化
這聽起來像一個完全不同的 function。 我會拆分接口,比如
public interface IGiveResults
{
string Results{get; }
}
和
public interface IGiveData<T>
{
T Data{get;}
}
不過,這並不能真正解決你的問題,所以我會給你經典的 Stack Exchange 答案,“不要做 A,做 B。沒有人做 A。”
如果你的目標是序列化,不要試圖強迫你在IEnumerable
中的東西返回各種不同的類型,然后試圖笨拙地爭論那個列表。
相反,請考慮將序列化和反序列化函數添加到接口,並讓對象接受序列化程序。 考慮:
public interface ISerializable
{
void Serialize(Serializer serializer);
void Deserialize(Deserializer deserializer);
}
您甚至可以將其包含在結果界面中:
public interface IGiveResults : ISerializable
{
string Results{get;}
}
現在您可以做的是,當您進入序列化或反序列化步驟時,您可以讓您的序列化程序自行關閉:
public class Serializer
{
public void SerializeAll(IEnumerable<IGiveResults> results)
{
foreach(var result in results)
{
result.Serialize(this);
}
}
public void Serialize<T>(T Data)
{
<do your thing>
}
}
這會翻轉你的問題,但我認為更好地完成你想做的事情。 現在,從ISerializable
接口繼承的子類可以執行以下操作:
public class YourIntSubclass : IGiveResults
{
public string Results{get; private set;} = "passed!";
private int[] Data = \\whatever
public void Serialize(Serializer serializer)
{
serializer.Serialize(Data);
}
}
您只需在序列化程序 class 中實現特定於類型的序列化,您就可以使用 go。 您可以使用模式匹配對序列化進行類型檢查,如果您忘記涵蓋一個案例,則可以拋出一個方便的異常,例如
public void Serialize<T>(T data)
{
switch(data)
{
case int intData:
<serialize an int>
break;
case float floatData:
<serialize a float>
break;
default:
throw new System.NotImplementedException("Forgot to implement a serializer for " + data.GetType().ToString());
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.