Parent Child Relation with restricted method access - c#

Let's assume I have the following interfaces:
public interface IChild
{
IParent MyParent { get; }
string Name { get; set; }
}
public interface IParent : IChild
{
IEnumerable<IChild> Children { get; }
}
In addition for the parent implementation there is the following abstract class:
public abstract class Parent : IParent
{
private List<IChild> _children = new List<IChild>();
public Parent(IParent parent, string name)
{
Name = name;
MyParent = parent;
}
public IEnumerable<IChild> Children => _children;
public IParent MyParent { get; }
public string Name { get; set; }
protected void Add(IChild child)
{
_children.Add(child);
}
protected void Remove(IChild child)
{
_children.Remove(child);
}
}
Now I use the following implementation based on the interfaces and abstract class above:
public class Tree : Parent
{
private Branch _left;
private Branch _right;
private Leaf _goldenLeaf;
public Tree(IParent parent, string name) :
base(parent, name)
{
_left = new Branch(this, "left branch");
Add(_left);
_right = new Branch(this, "left branch");
Add(_right);
_goldenLeaf = new Leaf(this, "the golden leaf");
Add(_goldenLeaf);
}
}
public class Branch : Parent
{
private Leaf _singleLeaf;
public Branch(IParent parent, string name) :
base(parent, name)
{
_singleLeaf = new Leaf(this, "the golden leaf");
Add(_singleLeaf);
}
}
public class Leaf : IChild
{
public Leaf(IParent parent, string name)
{
MyParent = parent;
Name = name;
}
public IParent MyParent { get; }
public string Name { get; set; }
public void DoSomething()
{
// How can I have a method in the parent which can only be called
// by the corresponding child. How to prevent the outside to call
// the method "Inform" on the parent?
MyParent.AskBeforeExecute(this, "data");
}
}
The main problem I have is that I want to call a method from the parent within the "DoSomething" call which is only accessible by the children. So the "AskBeforeExecute" method can not be in the public interface of the IParent definition because then the "outer" world can also call this method. I am not sure if my idea can be implemented at all with interface as I have right now. Anyway I am stuck a little bit and I am looking for a better pattern or idea to handle this?

Related

Call parent constructor but keep the reference of the child C#

I am calling the base constructor but somehow I need to point to the child one back. Take a look at the example bellow:
//Child
public CompanyEventsView(IAggregator aggregator, IRepository<CompanyEvents> repository, int i)
: base(aggregator, repository, i)
{
}
//Base
public BaseViewModelFor(IAggregator aggregator, IRepository<TSource> repository, int i)
{
Aggregator = aggregator;
var source = repository.GetKey(i);
this.MapFromSourceObject(source); // So "This" here should be pointing to the child class
}
Is there any way of doing this?
this and base do not refer to different instances, they are the same.
If your MapFromSourceObject method is defined in the child class, you can cast this to the child type like: (this as CompanyEventsView).MapFromSourceObject(source).
But this would defeat the whole point of inheritance.
Maybe define MapFromSourceObject as abstract or virtual in the base class?
If your base class depends the implementations of child classes, making the class itself abstract would be a better idea.
Maybe this example helps you a little bit with inheritance:
namespace CSharpConsoleApplication.Tests
{
using System;
using System.Collections.Generic;
using System.Linq;
class TemporaryTest
{
public static void Run()
{
Mother<FirstCompanyEvent> firstChild = new FirstChild(new FirstCompanyEvent("this is wrong"));
firstChild.Print();
Mother<SecondCompanyEvent> intChild = new SecondChild(new SecondCompanyEvent("you are too young to do this"));
intChild.Print();
}
}
public abstract class BaseCompanyEvent
{
protected string Value { get; private set; }
public BaseCompanyEvent(string value)
{
Value = value;
}
public abstract string GetMessage();
}
public class FirstCompanyEvent : BaseCompanyEvent
{
public FirstCompanyEvent(string value)
: base(value)
{ }
public override string GetMessage()
{
return "First born: " + Value;
}
}
public class SecondCompanyEvent : BaseCompanyEvent
{
public SecondCompanyEvent(string value)
: base(value)
{ }
public override string GetMessage()
{
return "Younger brother: " + Value;
}
}
public abstract class Mother<T> where T : BaseCompanyEvent
{
protected T CustomEvent { get; private set; }
public Mother(T customEvent)
{
CustomEvent = customEvent;
}
public abstract void Print();
}
public class FirstChild : Mother<FirstCompanyEvent>
{
public FirstChild(FirstCompanyEvent e)
: base(e)
{ }
public override void Print()
{
Console.WriteLine(CustomEvent.GetMessage());
}
}
public class SecondChild : Mother<SecondCompanyEvent>
{
public SecondChild(SecondCompanyEvent e)
: base(e)
{ }
public override void Print()
{
Console.WriteLine(CustomEvent.GetMessage());
}
}
}

Update the Base Class attributes when instantiate Child class C#

I want the following, is it possible in C#
public class BaseClass
{
public string Name {get;set;}
public DateTime Login {get;set;}
}
public class ChildA : BaseClass
{
public string SchoolName{get; set;}
public string ClassName{get; set;}
}
public class childB : BaseClass
{
public string StreetAdrees{get; set;}
}
Now I want that if I create an instance of any child class Name="John" and Login "2013-12-12" or from database already set its irritating to set these attribute for every class
just like that
ChildA obj=new ChildA();
obj.Name and obj.Login already have Data
Specify constructor in base class, then create constructors in child classes which inherit from base classes constuctor like below
public class ChildA : BaseClass
{
public ChildA():base(){}
public string SchoolName{get; set;}
public string ClassName{get; set;}
}
public class BaseClass
{
public BaseClass()
{
//set Data
.....
}
....
}
read more about base keyword
In the example below, children would actually point to the same instance of base
The example uses cache, but it could be anything else (session, application state, etc).
public class BaseClass
{
private string _name;
private DateTime _login;
public string Name
{
get
{
return Instance._name;
}
set
{
_name = value;
}
}
public DateTime Login
{
get
{
return Instance._login;
}
set
{
_login = value;
}
}
public static BaseClass Instance
{
get
{
// check if null, return a new instance if null etc...
return HttpContext.Current.Cache["BaseClassInstance"] as BaseClass;
}
set
{
HttpContext.Current.Cache.Insert("BaseClassInstance", value);
}
}
}
public class ChildA : BaseClass
{
public string SchoolName { get; set; }
public string ClassName { get; set; }
}
public class childB : BaseClass
{
public string StreetAdrees { get; set; }
}
testing it:
BaseClass.Instance = new BaseClass() { Login = DateTime.Now, Name = "Test" };
ChildA ch = new ChildA();
ChildA ch2 = new ChildA();
childB chb = new childB();
Response.Write(ch.Login.Millisecond);
Response.Write("<BR/>");
Response.Write(chb.Login.Millisecond);
Result:
906
906

Force EF 5 or 6 to map interface member

The question is very simple and direct: What do I have to do to make EF (5 or 6) create the database accordingly to this code
class Program
{
static void Main(string[] args)
{
Person parent = new ResponsablePerson();
parent.Name = "Father";
Person child = new Person();
child.Name = "Child";
child.Parent = parent;
using (PersonContext pc = new PersonContext())
{
pc.Persons.Add(parent);
pc.Persons.Add(child);
pc.SaveChanges();
}
Console.ReadKey();
}
}
public class Person : IPerson
{
[Key]
public string Name { get; set; }
public IPerson Parent { get; set; }
public virtual void Work()
{
Console.WriteLine("How much are you payng me? Ok I'll do it!");
}
}
public class ResponsablePerson : Person
{
public override void Work()
{
Console.WriteLine("Right Now!");
}
}
public class NotResponsablePerson : Person
{
public override void Work()
{
Console.WriteLine("Oh HELL NO!");
}
}
public interface IPerson
{
string Name { get; set; }
IPerson Parent { get; set; }
void Work();
}
The thing is that the database EF creates contains only 1 column for the name of the person...
public class Person : IPerson
{
public virtual Parent Parent { get; set; }
IParent IPerson.Parent
{
get { return this.Parent; }
set
{
if (!(value is Parent)) throw new ArgumentException();
this.Parent = (Parent)value;
}
}
}
As you can see, the trick is to have two properties, one to make EF work (returning type is Parent) and the other to satisfy the interface (returning type is IParent). The trick is possible by implementing the interface in an explicit way.

What is the best way to populate base properties?

I'm wondering if someone can help me with what is the best way to populate the base properties of a derived class. I would like to use one method to populate the properties of the base whether the base or the child is being used.
Here is an example of what I am asking:
public class Parent
{
public string Id {get; set;}
}
public class Child : Parent
{
public string Name {get; set;}
}
public Parent GetParent(int ID)
{
Parent myParent = new Parent();
//Lookup and populate
return Parent;
}
public Child GetChild(string name)
{
Child myChild = new Child();
//Use the GetParent method to populate base items
//and then
//Lookup and populate Child properties
return myChild;
}
I think you might be overcomplicating things a bit. Take a look at this code that uses inheritance and constructors to initialize objects:
public class Parent
{
public string Id {get; set;}
public Parent(string id)
{
Id = id;
}
}
public class Child : Parent
{
public string Name {get; set;}
public Child(string id, string name) : base(id) // <-- call base constructor
{
Name = name;
}
}
It uses constructors for initialization and the base keyword to call the parent constructor from the derived class. I would go this direction unless you really need to have a factory method construct your object.
Something like this if you don't want to do it in constructor.
Note: the constructor is not always called, especially if the type is desirialized using certain serializators.
public class Parent
{
public string Id {get; set;}
public virtual void InitPorperties() {
//init properties of base
}
}
public class Child : Base {
public override void InitProperties() {
//init Child properties
base.InitProperties();
}
}
After this you can use it like:
public Parent GetParent(int ID)
{
var myParent = new Parent();
parent.InitProperties();
return myParent;
}
public Parent GetChild(int ID)
{
var child= new Child();
child.InitProperties();
return child;
}
As anything it has other side of coin: the caller has to call InitProperties method in oder to get correctly initialized object.
If the serialization/desialization is not a concern in your case, stick with constructors, in practice call this methods inside ctors of every type (Parent, Child)
If you dont want to use a standard way to just
Child myChild = new Child();
myChild.Name = "name";
myChild.Id = "1";
You can populate them via the constructor like this.
public class Parent
{
public Parent(string id)
{
Id = id;
}
public string Id { get; set; }
}
public class Child : Parent
{
public Child(string id, string name)
: base(id)
{
name = Name;
}
public string Name { get; set; }
}
And when you isntanciate it
Child myChild = new Child("1", "name");
Which in my opinion is a quite neat way to do it.

Messing up with generics and graph modelling

I'm pretty new with C# and .NET. I'm trying to model a graph with heterogeneous data. I mean i would like to be able to do something like this:
// Simple graph modeling using generics
public class Node<T>
{
private T data;
public Node(T data)
{
this.data = data;
}
}
public class Edge<T, U>
{
private T source;
private U destination;
public Edge(T source, U destination)
{
this.source = source;
this.destination = destination;
}
}
Building it this way:
Node<Person> p = new Node<Person>(new Person("Red John"));
Node<Computer> c = new Node<Computer>(new Computer("MyComputer"));
graph.AddNode(p);
graph.AddNode(c);
graph.AddEdge(new Edge<Person, Computer>(p, c));
But of course the graph class definition won't let me do this:
public class Graph<T> where T : CommonBaseClass
I've also tried defining a base class for both person and computer, but of course it's not working. Any help/idea suggestion? I need heterogeneous data because i have to merge list of different nodes.
Thanks for helping!
In cases like this, it can be convenient to have your generic classes derive from non-generic classes. That way, you can refer to all types of Nodes through a simple Node class:
public class Node
{
public Node(object data)
{
this.Data = obj;
}
public object Data { get; protected set; }
}
public class Node<T> : Node
{
public Node(T data) : base(data) { }
new public T Data
{
get { return (T)base.Data; }
}
}
If type object is too primitive, you can use generic constraints instead:
public class Node
{
public Node(IGraphData data)
{
this.Data = obj;
}
public IGraphData Data { get; protected set; }
}
public class Node<T> : Node where T : IGraphData
{
public Node(T data) : base(data) { }
new public T Data
{
get { return (T)base.Data; }
}
}
public class Edge
{
}
public class Edge<T, U> : Edge
where T : Node where U : Node
{
// ...
}
Now, your Graph class can allow any type of Node and Edge:
public class Graph
{
public void AddNode(Node node) { /* ... */ }
public void AddEdge(Edge edge) { /* ... */ }
}
You could use an interface (say IGraphItem) instead of a common base class, and have both Nodes and Edges implement IGraphItem.
Then Graph could be changed to:
public class Graph<T> where T : IGraphItem
Let me know if I've misunderstood the question, I'm not 100% sure this is what you were asking about...
Yoy can do this by interface
public interface INode
{
List<INode> Nodes { get; set; }
}
public class Person : INode
{
public List<INode> Nodes { get; set; }
private string _name;
public Person(string name)
{
_name = name;
}
}
public class Computer : INode
{
public List<INode> Nodes { get; set; }
private int _number;
public Computer(int number)
{
_number = number;
}
}
And use:
var person = new Person("P1");
var computer = new Computer(1);
person.Nodes.Add(computer);
computer.Nodes.Add(person);

Categories

Resources