Restricting Generics to a subclass of the current class - c#

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

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?

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

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());
}

How to centralize boilerplate constructor code in C#?

All of my models in all of my applications inherit from IEntity:
public interface IEntity
{
long Id { get; set; }
dynamic RelatedItems { get; set; }
}
To prevent NullReferenceException, I always write a constructor in each model:
public class Book : IEntity
{
public Book()
{
RelatedItems = new System.Dynamic.ExpandoObject();
}
// other properties of the book
}
I need the RelatedItems because my infrastructure does many things on it.
However, this boilerplate constructor is a true pain.
When C# introduced Default Implementation I thought maybe default constructors also exist now, thus I created a constructor in my IEntity interface.
But I got this error:
IEntity.cs(7,16): error CS0526: Interfaces cannot contain instance constructors
Is there a way that I can prevent this boilerplate code?
I once tried to change it to abstract base class but it messed with EF Core and its inheritance.
As #AlanK pointed out the easiest thing would be to create an abstract class providing a boilerplate implementation of your properties including any initializers like this:
public abstract class BaseEntitiy : IEntity
{
public virtual long Id { get; set; }
public virtual dynamic RelatedItems { get; set; } = new System.Dynamic.ExpandoObject();
}
you can then inherit your Book class from BaseEntity overriding properties as needed:
public class Book : BaseEntitiy
{
// example override if you need any special getters or setters for books
public override long Id
{
get => base.Id;
set
{
if (value > 0)
{
base.Id = value;
}
}
}
}
Take a look at this code.
It's better to use generic instead of dynamic, so I added a BookRelatedItem class which you can add any further properties to.
About the EntityBase class, it's an abstraction of your entities so you don't have to initialize your RelatedItems each time.
public interface IEntity<T> where T : class
{
long Id { get; set; }
IEnumerable<T> RelatedItems { get; set; }
}
public abstract class EntityBase<T> : IEntity<T> where T : class
{
public long Id { get; set; }
public IEnumerable<T> RelatedItems { get; set; }
public EntityBase()
{
RelatedItems = new List<T>();
}
}
public class Book : EntityBase<BookRelatedItem>
{
// other properties of the book
}
public class BookRelatedItem
{
//some props
}

C# Override abstract property with more specific type

I have a rather simple problem, but I can't find a proper solution anywhere. I would like to specify an abstract object CustomValues as property in my abstract parent class. However, the class inheriting from it should be able to use a more specific type as an object for this property CustomValues. At first I thought I would solve the problem by an interface, but unfortunately that didn't work out either. How do you do something like that, that it works?
public abstract class MyAbstract {
public abstract object CustomValues { get; set; }
}
public class MyImplementation : MyAbstract {
public override MySpecificClass CustomValues { get; set; }
}
This will throw me three errors:
Missing implementation for getter
Missing implementation for setter
Type missmatch between type object and MySpecificClass
The solution suggested in the comments would look something like this. (I'm assuming CustomValues should be a collection of something.)
public class MyClass<T>
{
public ICollection<T> CustomValues { get; set; }
}
Or to ensure CustomValues itself cannot be reassigned, but can be accessed and added to:
public class MyClass<T>
{
public ICollection<T> CustomValues { get; } = new List<T>();
}
I think your original thought that use an interface (+ generic) was at the correct direction. In general you might want to add type constraints as well.
public interface ICustomValues {
....
}
public class MySpecificClass : ICustomValues {
....
}
public abstract class MyAbstract<T> where T : ICustomValues {
public abstract T CustomValues {
get;
set;
}
}
public class MyImplementation: MyAbstract<MySpecificClass> {
public override MySpecificClass CustomValues { get; set; }
}
Thanks to you all guys. I found the solution by using a generic properly:
public abstract class MyAbstract<T> {
public abstract T CustomValues { get; set; }
}
public class MyImplementation : MyAbstract<MySpecificClass> {
public override MySpecificClass CustomValues { get; set; }
}

Auto implement properties in inherited form

I'm creating a form to manage the reports of my application, the idea is that every report form inherits from this base form. My problem is that it contains several properties that HAVE to be assigned and i need to verify on every child form if I already called all, so... I'm wondering if there is a way to automatically make a call to all those properties.
This is part of the controller code:
public abstract partial class ReportsController()
{
public string Table{ get; set; }
public string Fields{ get; set; }
public string Condition{ get; set; }
public string Group{ get; set; }
public string Order{ get; set; }
public DataGridViewColumnCollection Columns{ get; set; }
public SortedList<string, string> ComboboxFields{ get; set; }
etc...
protected abstract void New();
protected abstract void Edit();
protected abstract void Print();
}
As you can see, methods are not a problem, they are abstract so they will have to be declared (and thanks to Resharper i will be warned if i missed one).
Child form:
public partial class frmReportGuards : ReportsController
{
public frmReportGuards()
{
code...
}
protected override void New()
{
code...
}
other methods...
}
And im looking for this:
public partial class frmReportGuards : ReportsController
{
public frmReportGuards()
{
//Auto assigned properties.
Table = "";
Fields = "";
Condition = "";
Group = "";
Order = "";
Columns = new DataGridViewColumnCollection();
ComboboxFields = new SortedList<string, string>();
}
protected override void New()
{
code...
}
other methods...
}
I don't know if I'm being senseless here :/ and I really need to get out of this doubt and if is possible... then simplify my work.
If your goal is to ensure that your properties are initialized to some default value, just add a constructor to ReportsController and set the properties there.
Now I understand, if you need to enforce implementation you should do it with abstract properties, inherited classes should implement then, and can be implemented with auto-properties:
public abstract class A
{
public abstract int MyProperty { get; set; }
}
public class B : A
{
public override int MyProperty { get; set; }
}
Short answer is not in C#5.0, in C#6.0 you have Auto-Property initializers, but I think that this is not what you are looking for.
Assuming you need a parameterless constructor, you can create an Init abstract method that is called from your base constructor and do a check if your initialization missed a property. There you can throw an exception or show a visual message indicating the failure.
So in base you do:
public abstract partial class ReportsController()
{
public ReportsController()
{
InitializeComponent();
//now your method
Init();
CheckProperties();
}
protected virtual void CheckProperties()
{
if(Table==null)
addVisualErrorMessage("Table property missing");
//and so on
}
protected abstract void Init();
}
But maybe you have to rethink your design and provide a single class with all the properties, so you can create an abstract method that forces you to provide all these important properties overriding a single method:
public class ComplexProperties
{
public string Table{ get; set; }
public string Fields{ get; set; }
public string Condition{ get; set; }
public string Group{ get; set; }
public string Order{ get; set; }
public DataGridViewColumnCollection Columns{ get; set; }
public SortedList<string, string> ComboboxFields{ get; set; }
}
public abstract partial class ReportsController()
{
public ComplexProperties Properties {get; private set;}
public ReportsController()
{
InitializeComponent();
//now your method
Properties= Init();
CheckProperties();
}
protected abstract ComplexProperties Init();
}
In any case I would prefer having a base constructor with parameters:
public abstract partial class ReportsController()
{
public ComplexProperties Properties {get; private set;}
public ReportsController(ComplexProperties properties)
{
Properties=properties;
CheckProperties();
}
}
And then initialize from the constructor:
public partial class MyReport:ReportsController
{
public MyReport():base(new ComplexProperties { Table="",...})
{
}
}
You could implement an interface for the properties that both the abstract base and the child classes need to implement.

Categories

Resources