I have the following interface representing a hierarchical data structure hence the name IHierachicalItem
public interface IHierachicalItem
{
IHierachicalItem Parent { get; set; }
IList<IHierachicalItem> Children { get; set; }
}
Now I have multiple classes that inherits from this interface:
public class HierachicalItemA : IHierachicalItem
{
public IHierachicalItem Parent { get; set; }
public IList<IHierachicalItem> Children { get; set; }
}
public class HierachicalItemB : IHierachicalItem
{
public IHierachicalItem Parent { get; set; }
public IList<IHierachicalItem> Children { get; set; }
}
public class HierachicalItemC : IHierachicalItem
{
public IHierachicalItem Parent { get; set; }
public IList<IHierachicalItem> Children { get; set; }
}
I wanted to extend the interface so that the classes return upon accessing its parent and children property the same class instead of the interface. So I thought about using a generic interface:
public interface IHierachicalItem<T> : IHierachicalItem
{
new T Parent { get; set; }
new IList<T> Children { get; set; }
}
Now I am facing the problem that I only want to have one instance of Children and don't call something like .OfType.ToList().
How can I achieve this?
public class HierachicalItemB : IHierachicalItem<HierachicalItemB>
{
IHierachicalItem IHierachicalItem.Parent { get { return this.Parent as IHierachicalItem; } set { this.Parent = (HierachicalItemB)value; } }
IList<IHierachicalItem> IHierachicalItem.Children { get { return this.Children.OfType<IHierachicalItem>().ToList(); } set { this.Children = value.OfType<HierachicalItemB>().ToList(); } }
public HierachicalItemB Parent { get; set; }
public IList<HierachicalItemB> Children { get; set; }
}
I also could have used .Cast<> instead of .OfType<> but this doesn't change the the fact that I would have to call .ToList() or if the Interface would say its an ObersavbleCollection again and again init a new ObservableCollection, any ideas?
You can't. Your IHierachicalItem interface demands a property with the signature IList<IHierachicalItem> Children, while IHierachicalItem<T> demands IList<T> Children. You need both properties implemented. This is the same for your other property.
That is why you need the implicit interface implementation to tell the compiler you comply to both interfaces. There is no way to workaround this, besides of dropping one of the interfaces.
Note: I think you T should be restricted to the IHierachicalItem<T> type:
public interface IHierachicalItem<T> : IHierachicalItem where T : IHierachicalItem
Related
I want to create an interface which can handle multiple other object of one interface.
I tried using the interface in the interface and using an object in the new class.
public interface IObject
{
double Value { get; set; }
}
public class FirstObject: IObject
{
double Value { get; set; }
}
public class SecondObject: IObject
{
string Titel { get; set; }
double Value { get; set; }
}
public interface ICollection
{
IObject[] Values { get; set; }
}
public class Collection: ICollection
{
SecondObject[] Values { get; set; }
}
Now I get the error, that my Collection doesn't implement the IObject[] Values member.
I thought when I use an object (SecondObject) which is implementing from the interface IObject the Collection should handle this.
What am I doing wrong and how can I solve this?
You might be off better here using generics:
public interface ICollection<T> where T : IObject
{
T[] Values { get; set; }
}
public class Collection : ICollection<SecondObject>
{
public SecondObject[] Values { get; set; }
}
The reason that it doesn't work now, is that the signature should match exactly. That means the Values should be an array of IObject, which it isn't. Using generics you can solve this, while keeping the type constraint.
A second, but inadvisable solution would be using an explicit interface implementation:
public SecondObject[] Values { get; set; }
IObject[] ICollection.Values
{
get
{
return this.Values;
}
set
{
this.Values = value?.Cast<SecondObject>().ToArray();
}
}
After having to refactor the inheritance chain in my current project for the third time I googled "Inheritance sucks" and found that the problem I'm having is not uncommon and composition is a recommended alternative solution.
I understand how you can use composition to add behavior in form of functions, but I'm having problems to come up with ways to add properties by the same means.
Let's say I want to model tree nodes. Every node has at least two properties: name and description.
class Node {
public string Name { get; set; }
public string Description { get; set; }
}
Other more specific nodes would inherit those properties, like so:
class StructuredNode : Node {
public List<Node> Children { get; set; }
}
How could I achieve similar re-usability of the property code without relying on inheritance and the problems that come with it?
Is there a design pattern for this or do I have to use inheritance in such a case?
Thanks in advance!
Edit:
Examples for the position "composition over inheritance":
ScottLilly
Wikipedia
Codingdelight
Rather then depending on class , you should depend son abstraction (this also one part of making use of composition) so for you case you should do like this
public interface INode {
string Name { get; set; }
string Description { get; set; }
}
class Node : INode {
public string Name { get; set; }
public string Description { get; set; }
}
class StructuredNode : INode {
public string Name { get; set; }
public string Description { get; set; }
public List<INode> Children { get; set; }
}
or you can also do this
//this is something similar to decorator pattern.
class StructuredNode {
private readonly INode _node;
public StructureNode(INode node)
{
_node = node;//now you can reuse function of any class which implements INode
}
public List<INode> Children { get; set; }
}
you should do like this also later on
List<Node> nodes = List<Node>();
StructuredNode sNode = new StructuredNode();
sNode.Children = nodes;
this is possible as all is based on abstraction. and all implementation now make use of INode
or
other solution suggested you in comment is make use of Decorator pattern. If you just want to extend you class without modifying it.
How could I archive similar re-usability of the property code without relying on inheritance and the problems that come with it?
The alternative to using inheritance is either interfaces or composition. However, for properties specifically, you're a bit stuck.
Interfaces cannot contain a default implementation the same way that a base class can. So while you can enforce that your classes use the correct "composed property structure", you can't make reusable methods available without implementing them in every class that implements the interface (or can you? More after the break!)
Composition simply doesn't exist in C# in a way that you can add properties to a class on the fly (unless you are satisfied with a Dictionary<string,string>). There may be some contrived method to technically make it work, but it won't be a good approach.
Interfaces + extension methods.
Extension methods can be used here to replace the reusable logic that you'd find in an inherited base class.
There is one drawback to this: The properties that you wish to access inside the extension methods need to be part of the interface contract and publically accessible.
Other than this drawback, it ticks the box on every other requirement you have.
First, an inheritance-based example:
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
public class PropertyComposedObject
{
public List<Property> Properties { get; set; }
public Property GetProperty(string name)
{
return this.Properties.SingleOrDefault(x => x.Name == name);
}
}
public class Person : PropertyComposedObject
{
}
If we were to use an interface instead, we would lose access to benefits such as a shared GetNode(string) method. You could add it as part of the interface, but each implementing class would then be responsible for implementing that method (leading you to copy/paste the same methods all over the place).
An interface example without extension methods:
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
public interface IPropertyComposedObject
{
List<Property> Properties { get; set; }
Property GetProperty(string name);
}
public class Person : IPropertyComposedObject
{
public List<Property> Properties { get; set; }
public Property GetProperty(string name)
{
return this.Properties.SingleOrDefault(x => x.Name == name);
}
}
But extension methods allows us to define the reusable method once but still access it from every class that implements the interface:
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
public interface IPropertyComposedObject
{
List<Property> Properties { get; set; }
}
public class Person : IPropertyComposedObject
{
public List<Property> Properties { get; set; }
}
public static class IPropertyComposedObjectExtensions
{
public Property GetProperty(this IPropertyComposedObject obj, string name)
{
return obj.Properties.SingleOrDefault(x => x.Name == name);
}
}
My attempt to minimize code duplication:
interface INodeProperties
{
string Name { get; set; }
string Description { get; set; }
}
class NodeProperties : INodeProperties
{
public string Name { get; set; }
public string Description { get; set; }
}
interface INode
{
INodeProperties NodeProps { get; set; }
}
class Node : INode
{
public INodeProperties NodeProps { get; set; } = new NodeProperties();
}
interface IStructuredNode
{
List<Node> Children { get; set; }
}
class StructuredNode: INode, IStructuredNode
{
public INodeProperties NodeProps { get; set; } = new NodeProperties();
public List<Node> Children { get; set; }
}
Downside: One more "hop" to get to the actual Properties ... :(
Have an INode interface, which encapsulates common properties.
This way you should have auto properties, then avoid putting logic in properties' getter and setter, because you can not reuse this logic.
Then repeating auto property definitions is not important and does not affect reusability.
If you need property change notification, it is better to use interceptor libraries such as postsharp.
I have the following interface declarations:
interface IOrder<T> where T: IOrderItem
{
IList<T> Items { get; set; }
}
interface IOrderItem
{
IOrder<IOrderItem> Parent { get; set; } // What do I put here?
}
I want the items in the list to have a reference to the header object, so it can use the ID and other fields from the header.
In my concrete classes, it complains that I don't implement "Parent" properly.
class StoreOrder : IOrder<StoreOrderItem>
{
public IList<StoreOrderItem> Items { get; set; }
}
class StoreOrderItem : IOrderItem
{
public StoreOrder Parent { get; set; } // This doesn't satisfy the interface
}
I tried setting up IOrderItem as IOrderItem<T> and passing in the Parent type, but that lead to circular reference since the Header class requries the Item class type... I got confused.
Any advice on how to implement this properly?
If you define your interfaces like so:
interface IOrder<T> where T : IOrderItem<T>
{
IList<T> Items { get; set; }
}
interface IOrderItem<T> where T : IOrderItem<T>
{
IOrder<T> Parent { get; set; }
}
You can then implement them like this to get the functionality that you expect:
class StoreOrder : IOrder<StoreOrderItem>
{
public IList<StoreOrderItem> Items { get; set; }
}
class StoreOrderItem: IOrderItem<StoreOrderItem>
{
public IOrder<StoreOrderItem> Parent { get; set; }
}
class StoreOrder : IOrder<StoreOrderItem>
{
public int Id { get; set; }
}
class StoreOrderItem : IOrderItem
{
public IOrder<IOrderItem> Parent { get; set; } // This doesn't satisfy the interface
}
You may not specialize - IOrder<IOrderItem> is more general than StoreOrder
Here's a solution for changing the interfaces:
interface IOrder<TOrder, TOrderItem>
where TOrderItem : IOrderItem<TOrder>
{
IList<TOrderItem> Items { get; set; }
}
interface IOrderItem<TOrder>
{
TOrder Parent { get; set; }
}
Making changes to StoreOrder and StoreOrderItem to support the interface changes AND adding a couple properties to each for a later test:
class StoreOrder: IOrder<StoreOrder, StoreOrderItem>
{
public DateTime Date { get; set; }
public IList<StoreOrderItem> Items { get; set; }
}
class StoreOrderItem : IOrderItem<StoreOrder>
{
public string ItemName { get; set; }
public decimal ItemPrice { get; set; }
public StoreOrder Parent { get; set; }
}
...and now creating StoreOrder and StoreOrderItem instances, and putting them through their paces:
void Main()
{
var so = new StoreOrder { Date = DateTime.Now };
var item = new StoreOrderItem {
Parent = so,
ItemName = "Hand soap",
ItemPrice = 2.50m };
so.Items = new [] { item };
Console.WriteLine(item.Parent.Date);
Console.WriteLine(so.Items.First().ItemName);
}
...when run, printed:
3/16/2012 10:43:55 AM
Hand soap
Another option is to scrap the above and take this solution and alter it by adding the Parent property with the desired type and using explicit interface implementation to avoid casting at the call-sites, making for a StoreOrderItem implementation something like this:
class StoreOrderItem : IOrderItem
{
public string ItemName { get; set; }
public decimal ItemPrice { get; set; }
public StoreOrder Parent { get; set; } // note: original implementation
IOrder<IOrderItem> IOrderItem.Parent { // explicit interface implementation
get { return (IOrder<IOrderItem>)this.Parent; }
set { this.Parent = (StoreOrder)value; }
}
}
My favorite of the above is the first proposal above with the two-generic parameters to IOrder and the unconstrained generic-parameter on IOrderItem. A previous version I had posted and have now edited had both interfaces each with the same two generic types each with the same constraints. I felt like this was going a bit overboard so I pared it back to the above implementation. Although there is a complete lack of constraints on TOrder type parameter to IOrderItem - attempts to fudge other types in its place (e.g., object) resulted in compile errors. Using TOrder instead of just calling it T provides a hint about the expected type in the absence of the type constraint. That will be my final edit - I feel it is the most succinct of my attempts; if you are curious I can provide the former implementation that had the double-generic-constrained-types on the interfaces, but this is at least my preferred this solution. cheers!
Declaration to satisfy the interfaces:
class StoreOrder : IOrder<StoreOrderItem>
{
// interface members
public IList<StoreOrderItem> Items { get; set; }
// own members
public int Id { get; set; }
}
class StoreOrderItem : IOrderItem
{
public IOrder<IOrderItem> Parent { get; set; }
}
To access custom members you will have to cast:
class StoreOrderItem : IOrderItem
{
void Test()
{
int id = ((StoreOrder)this.Parent).ID;
}
}
I have an application that has a concept of a Venue, a place where events happen. A Venue has many VenueParts. So, it looks like this:
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<VenuePart> VenueParts { get; set; }
}
A Venue can be a GolfCourseVenue, which is a Venue that has a Slope and a specific kind of VenuePart called a HoleVenuePart:
public class GolfCourseVenue : Venue
{
public string Slope { get; set; }
public virtual ICollection<HoleVenuePart> Holes { get; set; }
}
In the future, there may also be other kinds of Venues that all inherit from Venue. They might add their own fields, and will always have VenueParts of their own specific type.
Here are the VenuePart classes:
public abstract class VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public override string NameDescriptor { get { return "Hole"; } }
public int Yardage { get; set; }
}
My declarations above seem wrong, because now I have a GolfCourseVenue with two collections, when really it should just have the one. I can't override it, because the type is different, right? When I run reports, I would like to refer to the classes generically, where I just spit out Venues and VenueParts. But, when I render forms and such, I would like to be specific.
I have a lot of relationships like this and am wondering what I am doing wrong. For example, I have an Order that has OrderItems, but also specific kinds of Orders that have specific kinds of OrderItems.
Update: I should note that these classes are Entity Framework Code-First entities. I was hoping this wouldn't matter, but I guess it might. I need to structure the classes in a way that Code-First can properly create tables. It doesn't look like Code-First can handle generics. Sorry this implementation detail is getting in the way of an elegant solution :/
Update 2: Someone linked to a search that pointed at Covariance and Contravariance, which seemed to be a way to constrain lists within subtypes to be of a given subtype themselves. That seems really promising, but the person deleted their answer! Does anyone have any information on how I may leverage these concepts?
Update 3: Removed the navigation properties that were in child objects, because it was confusing people and not helping to describe the problem.
Here's one possible option using generics:
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public string NameDescriptor { get{return "I'm a hole venue"; } }
}
public class Venue<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
}
Here GolfCourseVenue has the collection VenueParts, which can contain HoleVenueParts or super classes HoleVenueParts. Other specializations of Venue would restrict VenueParts to containing VenueParts specific to that venue.
A second possibility is pretty much as you had it
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public string NameDescriptor { get{return "I'm a hole venue"; } }
}
public class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<VenuePart> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue
{
}
Now GolfCourseVenue has the collection VenueParts, which can contain VenueParts or super classes VenueParts. Here all specializations of Venue can contain any type of VenuePart which may or may not be appropriate.
In answer to your comment about covariance, I would propose something like this:
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public override string NameDescriptor { get{return "I'm a hole venue"; } }
}
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public abstract ICollection<VenuePart> VenueParts { get; }
}
public class GolfCourseVenue : Venue
{
private ICollection<HoleVenuePart> _holeVenueParts;
public GolfCourseVenue(ICollection<HoleVenuePart> parts)
{
_holeVenueParts = parts;
}
public override ICollection<VenuePart> VenueParts
{
get
{
// Here we need to prevent clients adding
// new VenuePart to the VenueParts collection.
// They have to use Add(HoleVenuePart part).
// Unfortunately only interfaces are covariant not types.
return new ReadOnlyCollection<VenuePart>(
_holeVenueParts.OfType<VenuePart>().ToList());
}
}
public void Add(HoleVenuePart part) { _holeVenueParts.Add(part); }
}
I look forward to the advice of others - but my approach is to use generics in this case. With generics, your GolfCourseVenue's "parts" are strong typed!
...and as I type this everyone else is saying generics too. HOW DO YOU overstackers type so dang fast?!
Anyways, pretending I'm still first -
public class VenuePart
{
}
public class HoleVenuePart : VenuePart
{
}
public abstract class Venue<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> Parts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
public string Slope { get; set; }
}
Also, as a 2nd option, you could use an interface too, so in case you didn't like the name Parts, you could call it Holes when the derived type is known to be a GolfCourse
public class VenuePart
{
}
public class HoleVenuePart : VenuePart
{
}
public interface IPartCollection<T> where T : VenuePart
{
ICollection<T> Parts { get; set; }
}
public abstract class Venue<T> : IPartCollection<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> Parts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
public string Slope { get; set; }
ICollection<HoleVenuePart> IPartCollection<HoleVenuePart>.Parts { get { return base.Parts; } set { base.Parts = value; }}
public virtual ICollection<HoleVenuePart> Holes { get { return base.Parts; } set { base.Parts = value;}}
}
You can use Covariance
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual IEnumerable<VenuePart> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue
{
public string Slope { get; set; }
public GolfCourseVenue()
{
List<HoleVenuePart> HoleVenueParts = new List<HoleVenuePart>();
HoleVenueParts.Add(new HoleVenuePart());
VenueParts = HoleVenueParts;
}
}
Assuming HoleVenuePart is inherited from VenuePart
If you remove "set" portions of both collections than it will make more sense: base class provides "all parts" collection, while derived classes have filtered view in addition to base class one.
Note: Depending on your needs making GolfVenue to be specialization generic of Venue<VenuePart> may not work as Venue<Type1> and Venue<Type2> will not have any good base class to work with.
Consider using interfaces instead of base classes as it would allow more flexibility in implementation.
public interface IVenue
{
public int Id { get; }
public string Name { get; }
public virtual IEnumerabe<VenuePart> VenueParts { get; }
}
public interface IGolfCourse : IVenue
{
public virtual IEnumerabe<HoleVenuePart> Holes { get; }
}
Now you can use GolfCourse:Venue from other samples but since it implements interface you can handle it in gnereic way too:
class GolfCourse:Venue<HoleVenuePart>, IGolfCourse {
public virtual IEnumerabe<VenuePart> Holes{ get
{
return VenueParts.OfType<HoleVenuePart>();
}
}
}
class OtherPlace:Venue<VenuePart>, IVenue {...}
List<IVenue> = new List<IVenue> { new GolfCourse(), new OtherPlace() };
Nothe that GolfCourse and OtherPlace don't have common parent class (except object), so without interface you can't use them interchangebly.
I have next code that represents graph edges and nodes (simplified for question):
public class Node
{
}
public class Edge
{
public Node Source { get; set; }
public Node Target { get; set; }
}
Now I want to extend this classes for describing mine topology:
public class MineNode : Node
{
public double FanPressure { get; set; }
}
public class MineTunnel : Edge
{
public double Length { get; set; }
public double CrossSectionArea { get; set; }
public MineTunnel()
{
Source = new MineNode();
Target = new MineNode();
}
}
The problem is that I want to access additional data provided by MineNode when using Source and Target properties, but I can access only Node fields because they are declared in base class:
MineTunnel t = new MineTunnel();
Console.WriteLine(t.Source.FanPressure); //Error
The only way to access FanPressure is to cast Source to MineNode but code become ugly this way.
Console.WriteLine(((MineNode)t.Source).FanPressure); //OK
The another way is maybe to use somehow generics in base class declaration. But I'm not sure is that a good practice in my situation.
So, how can I solve such problem - extend functionality of base class fields?
Thanks.
You could define your Edge type as generic, with constraints:
public class Edge<TNode> where TNode: Node
{
public TNode Source { get; set; }
public TNode Target { get; set; }
}
Through which you could redefine your MineTunnel type as:
public class MineTunnel : Edge<MineNode>
{
// Stuff
}
I think generics is the way to go here...
Try this:
public class Node
{
}
public class Edge<S, T>
where S : Node
where T : Node
{
public S Source { get; set; }
public T Target { get; set; }
}
Then you can extend the Node and Edge classes with:
public class MineNode : Node
{
public double FanPressure { get; set; }
}
public class MineTunnel : Edge<MineNode, MineNode>
{
public double Length { get; set; }
public double CrossSectionArea { get; set; }
public MineTunnel()
{
Source = new MineNode();
Target = new MineNode();
}
}
Please correct me if this is wrong or doesn't work... :)
MineTunnel t = new MineTunnel();
Console.WriteLine(t.Source.FanPressure); // Now this works without errors ;)