我来自c ++角落,并且对c#generics有一些不确定的问题。
问题:
解释
public abstract class Item{}
public abstract class ParentItem<T> : Item where T : Item{
public ObservableCollection<T> Childs;
}
public class ItemC : Item {}
public class ItemB : ParentItem<ItemC> {}
public class ItemA : ParentItem<ItemB> {}
public void NewChildItem<P, C>(P parent) where P : ParentItem<C> where C : Item, new()
{
C child = new C();
parent.Childs.Add(child); //From class ParentItem
}
public class MyEventArgs : EventArgs
{
public object Parent;
}
用法
public void NewItem(MyEventArgs e)
{
datas.NewChildItem(e.Parent); // That would be nice to avoid case analysis
datas.NewChildItem(e.Parent as ItemA); // Error cant resolve paramter type
//Following variant works, but is obvious ugly
if(e.Parent is ParentItem<ItemA>)
datas.NewChildItem<ParentItem<ItemA>,ItemA>(e.Parent as ParentItem<ItemA>)
else if(e.Parent is ParentItem<ItemB>)
datas.NewChildItem<ParentItem<ItemB>,ItemB>(e.Parent as ParentItem<ItemB>)
}
解释
我在3层上有一个带有HierarchicalDataTemplate的TreeView。 我的数据结构:
ItemA
-ItemB
-ItemB
-ItemC
ItemA
-ItemB
-ItemC
使用contextmenu我想添加一个孩子。我解雇MyEvent以获取父节点(如果是root则为null),它应该创建一个新的子节点。
如果我有设计错误,请告诉我。我想变得更好。
答案 0 :(得分:0)
我认为你做错了。你想拥有带孩子的物品。您可以为通用项目生成子项:
// Master-class with business-logic or so..
public abstract class Item
{
private static int nextId = 0; // Some Id-generator
public Item()
{
this.Id = nextId++;
}
public int Id { get; set; } // Id to see the difference between the objects.
public string Name { get { return this.GetType().Name + ":" + this.Id; } } // For Console..
}
// Class with business-logic for items which can have children
public abstract class ItemWithChildren<TChildClass> : Item where TChildClass : Item, new()
{
public ItemWithChildren()
{
this.Childs = new ObservableCollection<TChildClass>();
}
public ObservableCollection<TChildClass> Childs { get; set; }
public Item NewChildItem()
{
TChildClass newItem = new TChildClass();
Childs.Add(newItem);
return newItem;
}
public List<Item> GetChildItemsTypeless()
{
return this.Childs.Select(s => (Item) s).ToList();
}
}
// implementation of you concrete types..
public class ItemA : ItemWithChildren<ItemB>, IItemWithChildren { }
public class ItemB : ItemWithChildren<ItemC>, IItemWithChildren { }
public class ItemC : Item { }
// interface for managing children
public interface IItemWithChildren
{
Item NewChildItem();
List<Item> GetChildItemsTypeless();
}
public static void Test()
{
// Lets build some Items with an hierarchy
ItemA a = new ItemA();
ItemB b = (ItemB)a.NewChildItem(); // We cast here to explicit type to show that it's working.
Item b2 = a.NewChildItem(); // Here we got our anonymous Item
ItemC c = (ItemC)b.NewChildItem();
Item c2 = b.NewChildItem();
// Lets build an anonymous list - like your args-object
List<Item> items = new List<Item>() {a, b, b2, c, c2};
// some target for our new children..
List<Item> allItems = new List<Item>();
// let's add some children
foreach (Item item in items)
{
allItems.Add(item);
IItemWithChildren itemWithchildren = item as IItemWithChildren;
if (itemWithchildren != null)
allItems.Add(itemWithchildren.NewChildItem());
}
Console.WriteLine(" - - - Items with their children - - -");
foreach (Item item in allItems)
{
IItemWithChildren itemWithchildren = item as IItemWithChildren;
Console.WriteLine(item.Name + (itemWithchildren != null ? ": " + String.Join(", ", itemWithchildren.GetChildItemsTypeless().Select(s => s.Name)) : ""));
}
Console.WriteLine(" - - - Items by hierarchy - - -");
PrintItem(a);
}
public static void PrintItem(Item i, int level = 1)
{
Console.WriteLine(" ".PadRight(level*4) + i.Name);
IItemWithChildren itemWithchildren = i as IItemWithChildren;
if (itemWithchildren != null)
{
foreach (Item x in itemWithchildren.GetChildItemsTypeless())
{
PrintItem(x, level + 1);
}
}
}
Item
是你的&#34;大师班&#34;有一些商业逻辑。
ItemWithChildren<T>
类,其中包含可生成新子项的业务逻辑。
IItemWithChildren
是管理界面,知道你有孩子。
将NewchildItem
移到摘要ItemWithChildren
,您甚至不需要知道任何地方的课程。
在不知道IItemWithChildren
ItemWithChildren<T>