How to handle class inheritance in LiteDB with custom IDs - c#

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?

Related

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

Entity Framework - Multiple classes (tables) of the same interface - DbSet exposure?

public interface IQuestion {
// A couple of common properties go here, like Name, etc
}
/* Now follows multiple implementations of my interface, each of which has some custom properties */
public class TextBoxQuestion: IQuestion {
public int MaxLength { get; set; }
}
public class DateQuestion: IQuestion {
public DateTime MaxDate { get; set; }
public DateTime MinDate { get; set; }
}
public class MyRepo : DbContext {
**public DbSet<IQuestion> { get; set; } // Problem**
}
How would I go about implementing my DbContext? I can't expose an interface, as EF requires concrete implementations, which of course make sense, given the fact that I also have to generate a database.
Should I be exposing every IQuestion implementation I have, in the DbContext?
What is a better design - one huge table with all possible properties + discriminator column, or separate table for each implementation?
Edit:
I have added
public class BaseQuestion : IQuestion {
// Implements the common properties, plus:
[Key]
public int Id { get; set; }
}
and changed the Context to:
public class MyRepo : DbContext {
public DbSet<BaseQuestion> { get; set; }
}
EF now generates a 'huge table' + Discriminator column for me. The table 'automatically' includes the properties of all classes in my solution, which inherit the BaseQuestion. Is this the best practice?

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

Properties in a common interface

I have a bunch of properties which are common to two classes. I wanted to move those into an interface. Since these properties are both get and set, I'm not sure if I'd be allowed to set them from another class. I am implementing the interface in the class where I'd need these properties, but still I'm not being able to access these properties. My class is as follows:
public class PatchSurveyStartegy : IStrategy
{
public IEnumerable<IEnumerable<PointBase>> ReceiverGrid { get; set; }
public IEnumerable<IEnumerable<PointBase>> SourceGrid { get; set; }
public SourceParameters SourceParameters { get; set;}
public DeploymentParameters DeploymentParameters { get; set; }
public RovParameters RovParameters { get; set; }
}
So, IStrategy is the interface where I want to move all of these properties but I'm not getting access to them in this class:
internal double DeployRemainingLines()
{
return StepsForGivenLines(ReceiverGrid).Sum(step => step.CalculateStepTime());
}
I looked at these links: Interface should not have properties? and c# properties on Interface. Also, I dont want to put them in an abstract class, I want to use an interface.

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