Using abstract class property in interface in C# [duplicate] - c#

This question already has answers here:
C#: Interface to force list of items inheriting the interface
(3 answers)
Closed 10 months ago.
I am trying to deal with a problem of with interfaces and implementations. See code below.
public interface IMachine
{
string Name { get; set; }
List<IElement> Elements { get; set; }
List<IWire> Wires { get; set; }
}
public class ElementA : IElement { }
public class ElementB : IElement { }
public class WireA : IWire { }
public class WireB : IWire { }
public class MachineA : IMachine
{
public List<ElementA> Elements { get; set; }
public List<WireA> Wires { get; set; }
}
public class MachineB : IMachine
{
public List<ElementB> Elements { get; set; }
public List<WireB> Wires{ get; set; }
}
What I want to do in my program, is to iterate over IMachine elements stored in a list, and then access all Wire and Element members, without taking too much care about the exact type.
Is this even possible? I did some experiments with abstract classes, casting, but I'm stuck.
Well, of course code above will not compile as I get error, that I am missing implementation of interface member.
A/B classes vary in details (basic properties are same, but I use some specific ones for each class), so casting does not work, too.

Your fundamental problem is that a List<WireA> is not a List<IWire>, so you are not fulfilling the interface contract. If you want to access the lists as list of a specific type (rather than List<IElement>, for example) and avoid casting the elements, you could use generics:
public interface IMachine<TElement, TWire> where TElement : IElement, TWire : IWire
{
string Name { get; set; }
List<TElement> Elements { get; set; }
List<TWire> Wires { get; set; }
}
public class MachineA : IMachine<ElementA, WireA>
{
public List<ElementA> Elements { get; set; }
public List<WireA> Wires { get; set; }
}
public class MachineB : IMachine<ElementB, WireB>
{
public List<ElementB> Elements { get; set; }
public List<WireB> Wires{ get; set; }
}

Suppose your IWire required the implementation of GetName() and there existed at least one IWire object in your Wires collection then the code would return whatever was implemented by the instance of IWire's GetName() method.
var machines = new List<IMachine>();
machines.Add(new MachineA());
machines.Add(new MachineB());
machines.Add(new MachineA());
foreach(var machine in machines)
{
Console.WriteLine(machine.Wires[0].GetName());
}

Related

How to handle class inheritance in LiteDB with custom IDs

I would like to persist a class which implements an interface and can have various subclasses. I am just trying to understand how LiteDB handles this setup.
In particular I have a code structure like so:
public interface IItem
{
string UniqueKey { get; set;
string OtherProperties { get; set; }
}
public class Item : IItem
{
public string UniqueKey { get; set; }
public string OtherProperties { get; set; }
}
public class ItemOne : Item
{
public string ItemOneProperty { get; set; }
}
public class ItemTwo : Item
{
public string ItemTwoProperty { get; set; }
}
public class Main
{
public void Init()
{
// Can this apply to all interface implementations?
BsonMapper.Global.Entity<IItem>().Id(oid => oid.UniqueKey);
// This will apply to Item but not ItemOne or ItemTwo
BsonMapper.Global.Entity<Item>().Id(oid => oid.UniqueKey);
}
}
For reasons of wanting to keep the class structure clean, I do not want to use [BsonId] on the key. This means I need to use the BsonMapper to declare the ID. However, it looks like even though the mapper defines the ID on the base interface, it does not apply to any of the concrete classes.
Ideally, I do not want to declare the ID for every subclass in BsonMapper as - aside from there being many subclasses - it would create an unwanted dependency.
Does anyone know the best approach to solve this issue?

Restricting Generics to a subclass of the current class

I have two similar classes, so I made a parent class, and 2 classes which derive from it. The thing is that they are both trees of only their own type. So for now I have a parent class which holds a reference list of public IList<ParentTreeClass> Children { get; set; }. How can I change the ParentTreeClass to force it to be derived from ParentTreeClass not including it.
To give a bit more specific example, lets call the classes ParentTreeClass, ImportTree and ExportTree.
public class ParentTreeClass {
public ParentTreeClass Parent { get; set; }
public IList<ParentTreeClass> Children { get; set; }
// Other stuff.
}
public class ImportTree : ParentTreeClass {
// Some overrides.
}
public class ExportTree : ParentTreeClass {
// Some other overrides.
}
As said, once I have a ExportTree object, its children and parent should also be ExportTree and no other object.
I have thought about Generics like so:
public class ParentTreeClass<T> {
public T Parent { get; set; }
public IList<T> Children { get; set; }
// Other stuff.
}
But this is not restrictive enought, since I want T to be a child of ParentTreeClass. I tried adding where T : ParentTreeClass. This does not work, cause it tells me to use where T : ParentTreeClass<T>, then I run into issues understanding the second T.
Can I force a tree to be instances of the same type which derives from ParentTreeClass?
It's fairly simple to do.
public class ParentTreeClass<T> where T : ParentTreeClass<T> {
public T Parent { get; set; }
public IList<T> Children { get; set; }
// Other stuff.
}
public class ImportTree : ParentTreeClass<ImportTree> {
// Some overrides.
}
public class ExportTree : ParentTreeClass<ExportTree> {
// Some other overrides.
}
This has the drawback that you can go on to define a class like this:
public class ImportTree2 : ParentTreeClass<ExportTree> {
// Some overrides.
}
But, so long as you're careful with your definitions this works fine.
You could do like this:
public class ParentTreeClass<T> where T: ITree
{
public T Parent { get; set; }
public IList<T> Children { get; set; }
// Other stuff.
}
public interface ITree
{
IList<ITree> Children { get; set; }
ITree Parent { get; set; }
}
public class ImportTree : ParentTreeClass<ITree>, ITree
{
// Some overrides.
}
public class ExportTree : ParentTreeClass<ITree>, ITree
{
// Some other overrides.
}
Restriction is not subclass of parent but it restricts T by ITree implementations only

Creating Objects where multiple objects have the same properties

My program is starting to get pretty big. and i have found that its starting to do the same thing in multiple area's.
Im trying to figure out how i can make it more efficient.
So i have an object that looks like this
public class TreeViewNode
{
public TreeViewNode()
{
Children = new ObservableCollection<TreeViewNode>();
}
public String Name { get; set; }
public string Description { get; set; }
public ObservableCollection<TreeViewNode> Children { get; set; }
}
i also have another object that looks like this;
public class ComputerObject
{
public String Name { get; set; }
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
public ObservableCollection<Object> Children { get; set; }
}
Both these items need to have some of the same properties..
at the moment they both have the Children Property and the Name Property. but they both need to have some other common properties added to them.
so i have tried something like this.
public class BaseObject
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
public BaseObject()
{
Children = new ObservableCollection<object>();
}
}
public class ComputerObject: BaseObject
{
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
}
public class TreeViewNode: BaseObject
{
public String IconPath { get; set; }
}
Now this is just a cut down version of what i am implementing, i have alot of objects that share the same properties. and some that dont and mix and match. and i cannot figure out the best implimentation for this.
My Objects are becoming very cluttered, and when i rename a property i find that i have to rename it in several area's and this isnt the way its ment to be.
can someone please advise how i would implement multiple objects that share the same property names?
In my opinion you should not let classes inherit from one baseclass when these childclasses are not related to each other (like #Sriram Sakthivel asked Animal < Dog,Cat) just to share the same properties.
You should determine which classes are related (cat, dog are animals; car, motorcycle are vehicles) and then create baseclasses based on these "groupings".
I would look into decorator pattern. In short, you dont share common properties via inheritance. You make classes that contain common properties, and use these classes as properties in your end classes.
EDIT: Example is actually just a standard composition, it should work nevertheless
E.G.
public class Decorator1
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
}
public class Decorator2
{
public long Id { get; set; }
}
public class ClassA
{
public Decorator1 TreeNodeImpl;
}
public class ClassB
{
public Decorator1 TreeNodeImpl;
public Decorator2 LongIdImpl;
}

Problem implementing generic interface

I have a base DLL which defines some basic structure and operation for a key concept within our business. This dll is then included in specific web services for each vendor that implement the specific business rules for interacting with that vendor. (While the basic concepts are the same the implementations are very different and can change independently.)
In the base dll I have a series of interfaces set up as such
public interface IVendor
{
string Name { get; set; }
}
public interface IVendor<TC> : IVendor where TC : IAccount
{
IEnumerable<TC> Accounts { get; set; }
}
public interface IAccount
{
string Name { get; set; }
}
public interface IAccount<TP, TC> : IAccount where TP : IVendor
where TC : IExecutionPeriod
{
TP Vendor{ get; set; }
IEnumerable<TC> ExecutionPeriods { get; set; }
}
This continues down several more tiers, and everything compiles fine.
The problem comes when I try to implement this down in the service.
public class FirstVendor : IVendor<FirstVendorAccount>
{
public string Name { get; set; }
public IEnumerable<FirstVendorAccount> Accounts { get; set;}
}
public class FirstVendorAccount : IAccount<FirstVendor, FirstVendorExecutionPeriod>
{
public FirstVendor Vendor { get; set; }
public string Name { get; set; }
public IEnumerable<FirstVendorExecutionPeriod> ExecutionPeriods { get; set; }
}
I get a compiler error that IVendor, IAccount, etc. do not have type parameters. Which is particularly odd because when I asked it to implement the interface it included all of the members from both relevant interfaces.
It looks like you have a circular reference - FirstVendorAccount needs to know about FirstVendor before it can compile and vice versa.
Make one of these the 'dominant' class with the generic type, then the other can just return the base interface.
For instance:
public interface IVendor
{
string Name { get; set; }
}
public interface IVendor<TC> : IVendor where TC : IAccount
{
IEnumerable<TC> Accounts { get; set; }
}
public interface IAccount
{
string Name { get; set; }
}
// no longer needs IVendor<TC> before it can be compiled
public interface IAccount<TC> : IAccount where TC : IExecutionPeriod
{
IVendor Vendor{ get; set; }
IEnumerable<TC> ExecutionPeriods { get; set; }
}
It's worth looking at whether you really need all the generic typing - you may be better off with the non-generic underlying interfaces as these will be much easier to code with.

c# Class Design with Generics

How can i make the following class as general as possible (for maximum reuse) without creating too many classes of the same type, albeit with one extra property.
I want to avoid writing 3 slightly different versions of the same class
1# Class with No SubContent
public class Content
{
public string PageName { get; set; }
}
2# Class with Subcontent
public class Content
{
public string PageName { get; set; }
public IList<Content> SubContent {get; set;} //same as class
}
3# Class with sub content of another type
public class Content
{
public string PageName { get; set; }
public IList<DetailContent> SubContent {get; set;} //Note the different def
}
Of course i can create a generic class, but i find this confusing for consumers. It is inferring that the class is of Type T, when in fact its the Property that requires the type
public class Content<T>
{
public string PageName { get; set; }
public IList<T> SubContent {get; set;} //Note the different def
}
Generic Properties are not supported. So are there any patterns or suggestion on how i can handle this problem?
Perhaps you can have a look at the Composite Design Pattern
whats wrong with:
public class Content<T>
{
public string PageName { get; set; }
public IList<T> SubContent { get; set; } //Note the different def
}
?
it works you know...
What about
public class Content
{
public string PageName { get; set; }
}
public class ContentWithSubContent<T> : Content
{
public IList<T> SubContent { get; set; }
}
and if you want to be able to access SubContent not knowing the actual type, you could use
public class Content
{
public string PageName { get; set; }
}
public interface IContentWithSubContent
{
IEnumerable SubContent { get; }
}
public class ContentWithSubContent<T> : Content, IContentWithSubContent
{
public IList<T> SubContent { get; set; }
IEnumerable IContentWithSubContent SubContent
{
get { return this.SubContent; }
}
}
that way you can access the SubContent property bypassing generics if you need to, by using IContentsWithSubContent rather than Content.
Why not make an interface for the content classes:
public interface IContent {
public function GetContent()
}
and then you can use
List<IContent> in your content class?
you could even make the interface generic

Categories

Resources