[英]How to force a class to implement a property that derives from a specific base class/interface (rather than is of a specific type)
[英]Create an instance of a List where the type derives from a base class and an interface
我有一個類,該類將存儲從基類派生並實現接口的對象。 在此示例中,所有類型都派生自UIElement
並實現我的接口IDropTarget
。
所以在我的課堂上,我可以用一種奇妙的方式使用泛型類型推斷來要求它,而不必將所有內容都限制在特定的基類中
public void AddDropTarget<TTarget>(TTarget target)
where TTarget : UIElement, IDropTarget
{
target.DoSomethingAsUIElement();
target.DoSomethingAsIDropTraget();
// Now I want to save it for another method
list.Add(target);
}
public void DoStuff()
{
foreach(var item in list)
{
item.MoreUIElementAndDropStuff();
}
}
不幸的是,我似乎沒有辦法存儲此TTarget受限列表。 我不能將其限制為特定的類型,因為我已經有多個類從UIElement派生(矩形,按鈕,網格等),而且我沒有辦法使所有這些對象都從基本類型派生。
我的下一個解決方案是存儲每種類型的列表。 我需要弄清楚這些開銷是否值得,而不是每次使用它們時都要投射對象。
您不能通過這種方式將兩種不同的類型添加到列表中。 你基本上是說,你想他們一般類型設置為X
或Y
。 想象一下,當您進行一次foreach
時會發生什么,編譯器將不知道您是否需要UIElement
或IDragDrop
。
您只需要手動維護類型安全。 使用私有列表(我想就像您正在做的那樣),然后手動進行投射。 取決於您要使用哪種類型或任何類型。
public class MyClass {
private _list = new List<object>(); // don't store any type info for now
public void AddDropTarget.... /* this is already correct */
public void RunUiStuff() {
// get all items that are of type UIElement. Items of wrong type will be ignored
foreach(var e in _list.OfType<UIElement>()) {
}
}
public void RunDropStuff() {
// cast works as well, but will throw if any object is not the correct type
foreach(var e in _list.Cast<IDropTarget>()) {
}
}
}
如果您不想強制轉換,則可以使用裝飾器模式的變體來創建所需的公共基類。
//our new base type
public interface IElementAndDropTarget : IDropTarget
{
void DoSomethingAsUIElement();
void MoreUIElementAndDropStuff();
}
// our decorator. We need to store UIElement and IDropTarget
// as different fields. The static "Make" is giving you
// the compile-time guarantee that they both refer
// to the same class
public class UIElementDecorator : IElementAndDropTarget
{
private readonly UIElement t;
private readonly IDropTarget dt;
private UIElementDecorator(UIElement t, IDropTarget dt)
{
this.t=t;
this.dt=dt;
}
public static UIElementDecorator Make<T>(T t) where T: UIElement, IDropTarget
{
return new UIElementDecorator(t,t);
}
public void DoSomethingAsUIElement() {t.DoSomethingAsUIElement();}
public void MoreUIElementAndDropStuff(){t.MoreUIElementAndDropStuff();}
public void DoSomethingAsIDropTarget() {dt.DoSomethingAsIDropTarget();}
}
這樣,您的列表可以是
public List<IElementAndDropTarget> list = new List<IElementAndDropTarget>();
在AddDropTarget
,可以使用修飾的類將其填充為:
list.Add(UIElementDecorator.Make(target));
就是這樣。 您的其余代碼可以保持不變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.