L'objectif final de ce post est de surcharger la méthode ToString() d'une implémentation concrète d'une classe de base générique tout en étant capable de rechercher l'implémentation à l'aide de la technique d'aplatissement Linq. Donc, si vous lisez ceci et voyez un meilleur moyen faites le moi savoir. J'utilise des contrôles Telerik pour Silverlight et ils ne changeront pas leur API pour permettre à certaines de leurs propriétés de contrôle d'être liées aux données et s'appuient plutôt sur la méthode ToString() de l'objet auquel ils sont liés. Oui, stupide .. De toute façon voici ce que j'ai.Implémentation concrète de la classe de base générique et méthode d'extension
Contrôle RadTreeView sur ma page. La propriété FullPath de chaque nœud dans l'arborescence utilise la méthode ToString() de chaque élément auquel elle est liée (donc c'est ce que j'ai besoin de surcharger).
J'ai dû créer une classe "intermédiaire" pour améliorer ma classe de modèle de base afin qu'elle puisse être liée comme une hiérarchie dans l'arborescence puis une implémentation concrète de cette classe générique pour remplacer ToString(). Maintenant, le problème est que j'ai une extension Linq qui explose car elle ne peut pas convertir l'implémentation concrète à la classe générique de base. J'aime les génériques mais c'est trop pour moi. Besoin d'aide pour résoudre le problème de méthode d'extension.
classe générique intermédiaire:
public class HeirarchicalItem<T> : NotifyPropertyChangedBase, INotifyCollectionChanged where T : class
{
public event NotifyCollectionChangedEventHandler CollectionChanged;
public virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs ea)
{
if (CollectionChanged != null)
CollectionChanged(this, ea);
}
public HeirarchicalItem() { }
public HeirarchicalItem(T item)
{
Item = item;
}
public HeirarchicalItem(IEnumerable<T> collection)
{
CopyFrom(collection);
}
private T _item;
public T Item
{
get
{
return _item;
}
set
{
_item = value;
RaisePropertyChanged<HeirarchicalItem<T>>(a => a.Item);
}
}
private ObservableCollection<HeirarchicalItem<T>> _children = new ObservableCollection<HeirarchicalItem<T>>();
public virtual ObservableCollection<HeirarchicalItem<T>> Children
{
get { return _children; }
set
{
_children = value;
RaisePropertyChanged<HeirarchicalItem<T>>(a => a.Children);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
private void CopyFrom(IEnumerable<T> collection)
{
if ((collection != null))
{
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
HeirarchicalItem<T> newHeirarchicalItem = new HeirarchicalItem<T>(enumerator.Current);
Children.Add(newHeirarchicalItem);
RaisePropertyChanged<HeirarchicalItem<T>>(a => a.Children);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
}
}
}
}
}
Modèle de base Classe: (données est ballottée et du service WCF Ria utilisant cette classe)
public class tbl_Path : EntityBase, IFullPath, IEquatable<tbl_Path>, IEqualityComparer<tbl_Path>
{
public tbl_Path();
public int GetHashCode(tbl_Path obj);
public override string ToString();
public DateTime CreateDate { get; set; }
public short Depth { get; set; }
public string FullPath { get; set; }
public bool IsAuthorized { get; set; }
public bool IsSelected { get; set; }
public string Name { get; set; }
public override IEnumerable<Operation> Operations { get; }
public int? ParentPathID { get; set; }
public int PathID { get; set; }
public Guid SecurityKey { get; set; }
public EntityCollection<tbl_Configuration> tbl_Configuration { get; set; }
public EntityCollection<tbl_Key> tbl_Key { get; set; }
public EntityCollection<tbl_SecurityACL> tbl_SecurityACL { get; set; }
public EntityCollection<tbl_SecurityInheriting> tbl_SecurityInheriting { get; set; }
public EntityCollection<tbl_Variable> tbl_Variable { get; set; }
}
mise en œuvre concrète de sorte que Je peux remplacer ToString():
public class HeirarchicalPath : HeirarchicalItem<tbl_Path>
{
public HeirarchicalPath()
{
}
public HeirarchicalPath(tbl_Path item)
: base(item)
{
}
public HeirarchicalPath(IEnumerable<tbl_Path> collection)
: base(collection)
{
}
public override string ToString()
{
return Item.Name; **// we override here so Telerik is happy**
}
}
Enfin, voici la méthode d'extension Linq qui explose pendant la compilation car j'ai introduit une implémentation concrète de ma classe de base générique.
public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse)
{
foreach (T item in source)
{
yield return item;
IEnumerable<T> seqRecurse = fnRecurse(item);
if (seqRecurse != null)
{
foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse))
{
yield return itemRecurse;
}
}
}
}
code réel qui est la rupture: (x.Children est mise en évidence avec l'erreur)
Cannot implicitly convert type
'System.Collections.ObjectModel.ObservableCollection<HeirarchicalItem<tbl_Path>>' to
'System.Collections.Generic.IEnumerable<HeirarchicalPath>'. An explicit conversion
exists (are you missing a cast?)
HeirarchicalPath currentItem = this.Paths.Traverse(x => x.Children).Where(x => x.Item.FullPath == "$/MyFolder/Hello").FirstOrDefault();