我无法将一个类转换为它的基本接口。我有以下(简化):
public interface ITaxonomy
{
string CommonName { get; set; }
string ScientificName { get; set; }
}
public interface ITaxonomyHasChildren<TChild> : ITaxonomy where TChild : ITaxonomy
{
ICollection<TChild> Children { get; set; }
}
public interface ITaxonomyHasParent<TParent> : ITaxonomy where TParent : ITaxonomy
{
TParent Parent { get; set; }
}
我需要在我的VM中提取数据:
private void SelectedEntityChanged(ITaxonomy selectedEntity)
{
CommonName = selectedEntity.CommonName;
ScientificName = selectedEntity.ScientificName;
Children = selectedEntity.GetType().GetProperty(nameof(ITaxonomyHasChildren<ITaxonomy>.Children))?
.GetValue(selectedEntity) as ICollection<ITaxonomy>;
Parent = selectedEntity.GetType().GetProperty(nameof(ITaxonomyHasParent<ITaxonomy>.Parent))?
.GetValue(selectedEntity) as ITaxonomy;
}
Children
部分不起作用,我假设是因为它不想从ICollection<MyClass>
转换为ICollection<ITaxonomy>
我该如何做到这一点?
答案 0 :(得分:4)
为了使其工作,您需要创建通用接口covariant。但由于ICollection<T>
不具有协变性,因此如果您负担得起,则还需要将Children
类型更改为IReadOnlyCollection<TChild>
并删除设置者。
public interface ITaxonomyHasChildren<out TChild> : ITaxonomy where TChild : ITaxonomy
{
IReadOnlyCollection<TChild> Children { get; }
}
public interface ITaxonomyHasParent<out TParent> : ITaxonomy where TParent : ITaxonomy
{
TParent Parent { get; }
}
这也可以让你避免反思:
private void SelectedEntityChanged(ITaxonomy selectedEntity)
{
CommonName = selectedEntity.CommonName;
ScientificName = selectedEntity.ScientificName;
Children = (selectedEntity as ITaxonomyHasChildren<ITaxonomy>)?.Children;
Parent = (selectedEntity as ITaxonomyHasParent<ITaxonomy>)?.Parent;
}
示例类实现:
class Taxonomy : ITaxonomy, ITaxonomyHasChildren<Taxonomy>, ITaxonomyHasParent<Taxonomy>
{
public string CommonName { get; set; }
public string ScientificName { get; set; }
public Taxonomy Parent { get; set; }
public List<Taxonomy> Children { get; set; } = new List<Taxonomy>();
IReadOnlyCollection<Taxonomy> ITaxonomyHasChildren<Taxonomy>.Children => Children;
}
答案 1 :(得分:2)
调用
selectedEntity.GetType()
.GetProperty( nameof(ITaxonomyHasChildren<ITaxonomy>.Children) )
.GetValue( selectedEntity )
是一种非常迂回的做事方式。
您不需要使用反射系统来完成基本的面向对象的东西。
此外,你的类型非常复杂,没有充分的理由。
请考虑一下:
public interface IParent<T> //note: general-purpose interface unrelated to taxonomies
{
ICollection<T> Children { get; }
}
public interface IChild<T> //note: general-purpose interface unrelated to taxonomies
{
T Parent { get; set; }
}
public interface ITaxonomy
{
string CommonName { get; set; }
string ScientificName { get; set; }
IParent<ITaxonomy> AsParent {get; } //returns `null` if not a parent
IChild<ITaxonomy> AsChild {get; } //returns `null` if not a child
}
IChild<ITaxonomy> selectedEntityAsChild = selectedEntity.AsChild;
if( selectedEntityAsChild != null )
{
ITaxonomy parent = selectedEntityAsChild.Parent;
...
}
IParent<ITaxonomy> selectedEntityAsParent = selectedEntity.AsParent;
if( selectedEntityAsParent != null )
{
ICollection<ITaxonomy> children = selectedEntityAsParent.Children;
...
}