I'm playing with C# generics and interfaces today and trying implement classic definition of Graphs. Here is my best attempt (for exercise only):
interface IVertex
{
string Name { get; set; }
}
interface IEdge<V> where V : IVertex
{
V From { get; set; }
V To { get; set; }
}
interface IGraph<V, E> where E: IEdge<V> where V: IVertex
{
IList<V> Vertices { get; }
IList<E> Edges { get; }
}
class Vertex : IVertex
{
public string Name { get; set; }
public Vertex(string name)
{
Name = name;
}
}
class Edge<V> : IEdge<V> where V: IVertex
{
public V From { get; set; }
public V To { get; set; }
public Edge(V from, V to)
{
From = from;
To = to;
}
}
class Graph<V, E> : IGraph<V, E> where E: IEdge<V> where V : IVertex
{
public IList<V> Vertices { get; } = new List<V>();
public IList<E> Edges { get; } = new List<E>();
}
But I think, that I'm doing something wrong, because in following usage:
var a = new Vertex("A");
var b = new Vertex("B");
var c = new Vertex("C");
var x = new Edge<Vertex>(a, b);
var y = new Edge<Vertex>(b, c);
var z = new Edge<Vertex>(c, a);
var graph = new Graph<Vertex, Edge<Vertex>>()
{
Vertices = { a, b, c },
Edges = {x, y, z}
};
I need to specify the generic argument Vertex (at line new Graph<Vertex, Edge<Vertex>>()) twice...
Without more context, it's not clear what your constraints and requirements are. But, depending on what you're trying to accomplish, the syntax you currently have may be required, to ensure that your IList<E> is declared appropriately.
It is also possible that you don't require the Graph class to have the exact IEdge<V> type. If so, then you could declare it like this:
class Graph<V> : IGraph<V, IEdge<V>> where V : IVertex
{
public IList<V> Vertices { get; } = new List<V>();
public IList<IEdge<V>> Edges { get; } = new List<IEdge<V>>();
}
In this approach, you will not be able e.g. to assign Edges to a variable of type IList<E> where E is some type other than IEdge<V>. For example, this wouldn't work, while it would work if you require both types to be specified:
IList<Edge<Vertex>> list = graph.Edges;
It all depends on how you actually want to use these types.
Related
My code structure is something like this
class Drawing()
{
ObjectType = "Drawing";
}
class Shape() : Drawing()
{
DrawingType = "Shape";
}
class square() : Shape()
{
ShapeType = "square";
}
class circle() : Shape()
{
ShapeType = "circle";
}
class triangle() : Shape()
{
ShapeType = "triangle";
}
class lines() : Drawing()
{
DrawingType = "lines";
}
class horizontal() : lines()
{
linesType = "horizontal";
}
class vertical() : lines()
{
linesType = "vertical";
}
etc...
I am trying to figure out the right logic in how to solve this problem so the picture is a simple representation of what I have.
I have a object structure of something like in the picture where they're all inheriting the level above them. They all have properties of its type. They would all have ObjectType, and the 2nd level has DrawingType, and the 3rd level has either ShapeType, LineType, or PointType...
So for example, square would have
square {
ObjectType = "drawing";
DrawingType = "shapes";
ShapeType = "square"
}
However, vertical would have different properties
vertical {
ObjectType = "drawing";
DrawingType = "lines";
LineType = "vertical"
}
Now my problem is, lets say I wanted a user to select something based on their input, how would i do it?
Like lets say the user typed "square", how would I select square? It would be easy if the properties were the same cause I could just compare them. But how would I do it with a structure like this?
As these all classes are derived from one base class hence all the child classes contains the property coming from parents. Object level comparison will lead you comparison of one Drawing object to another as all the objects are derived from there only. Hence i have implemented IComparer to get your desired result ->
Here is the code ->>
Main Class :
Drawing drawing1 = new Drawing();
Drawing drawing2 = new Drawing();
drawing2.ObjectType = "newdrawing";
Shape shape = new Shape();
triangle triangle1 = new triangle();
triangle triangle2 = new triangle();
triangle2.ShapeType = "another";
//all -1 is not equals and 0 is equals
int result1 = drawing1.Compare(drawing1, drawing2);
int result2 = drawing1.Compare(drawing1, drawing1);
int result3 = drawing1.Compare(drawing1, shape);
int result4 = shape.Compare(shape, triangle1);
int result5 = triangle1.Compare(triangle1, triangle2);
Other classes :
public class Drawing : IComparer
{
public string ObjectType { get; set; } = "Drawing";
public int Compare(object x, object y)
{
//returning 0 is equals
if (x.GetType().Name == y.GetType().Name)
{
switch (x.GetType().Name)
{
case "Drawing":
return ((Drawing)x).ObjectType == ((Drawing)y).ObjectType ? 0 : -1;
case "Shape":
return ((Shape)x).DrawingType == ((Shape)y).DrawingType ? 0 : -1;
case "square":
return ((square)x).ShapeType == ((square)y).ShapeType ? 0 : -1;
case "triangle":
return ((triangle)x).ShapeType == ((triangle)y).ShapeType ? 0 : -1;
default:
return -1; // Not equal
}
}
return -1; // Not equal
}
}
class Shape : Drawing
{
public string DrawingType { get; set; } = "Shape";
}
class square : Shape
{
public string ShapeType { get; set; } = "square";
}
class circle : Shape
{
public string ShapeType { get; set; } = "circle";
}
class triangle : Shape
{
public string ShapeType { get; set; } = "triangle";
}
class lines : Drawing
{
public string DrawingType { get; set; } = "lines";
}
class horizontal : lines
{
public string linesType { get; set; } = "horizontal";
}
class vertical : lines
{
public string linesType { get; set; } = "vertical";
}
Hope this will work for you. please write back with you code snippet specifically not working. Cheers
I have a list of source classes derived from a base source class and a list with destination classes derived from a base destination class. There is only one destination class corresponding to a source class. I want to make a generic converter which updates an existing destination object, given his corresponding source object.
Updated completely:
I have the following code:
using System;
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
S1 newItem = new S1()
{
Age = 11,
Name = "John"
};
D1 oldItem = new D1()
{
Age = 10
};
//there is an item in a database which is of D1 type. This convertor receives an object S1 in order to update the D1 item.
// the rule is that Sx updatates Dx (where x is 1,2,3,4,5...)
Convertor<S1, D1> convertor = new Convertor<S1, D1>(newItem, oldItem);
S2 newItem2 = new S2()
{
City = "London",
Name = "Lynda"
};
D2 oldItem2 = new D2()
{
City = "Paris"
};
Convertor<S2, D2> convertor2 = new Convertor<S2, D2>(newItem2, oldItem2);
Console.ReadKey();
}
}
public abstract class SourceDomain
{
public string Name { get; set; }
internal abstract void SetItem<Y>(Y oldItem) where Y : DestinationDomain;
}
public class S1 : SourceDomain
{
public int Age { get; set; }
internal override void SetItem<Y>(Y oldItem)
{
Console.WriteLine("here I want to update the age of oldItem (10) with the new value (11)");
//oldItem.Age = Age;
}
}
public class S2 : SourceDomain
{
public string City { get; set; }
internal override void SetItem<Y>(Y oldItem)
{
Console.WriteLine("here I want to update the city of oldItem Paris with the new value London");
// oldItem.City = City;
}
}
public class DestinationDomain { }
public class D1 : DestinationDomain
{
public int Age { get; set; }
}
public class D2 : DestinationDomain
{
public string City { get; set; }
}
public class Convertor<X, Y> where X : SourceDomain where Y : DestinationDomain
{
protected X item;
protected Y oldItem;
public Convertor(X newObject, Y oldObject)
{
item = newObject;
oldItem = oldObject;
//here I want to call, depending of item type, the proper method, not the base one.
item.SetItem(oldItem);
}
}
}
SourceDomain and DestinationDomain are base classes and there are a lot of derived classes for each of them S1, S2, D1, D2, etc.
This converter receives two classes as types and two objects of that classes and tries to update the destination item of type Y with source item of type X.
In the above example, I want to change update the age of the D1 oldItem variable with 11, and the City oldItem2 with the "London" value, but I cannot access that properties in SetItem method.
This needs to be done with a combination of inheritance and generics, and we'll make the two work together with generic type constraints.
Here are the requirements as I understand them:
You've got some data you want to copy from Source to Destination; one kind of data has an Age, one has a City, maybe another has a Poodle or a SwimmingPool. We'll define an interface that says: "This is a data object which can copy its own properties from another object of the same type", and we'll put all our data in little classes which know how to copy themselves. The "I can copy things like me" interface doesn't know what properties will be copied; it just requires the concrete class to implement a method that knows those details internally. As far as this example goes it could be a base class, but my assumption is the “copyability” isn’t the core indentity of these objects. It’s not what they represent; it’s just one thing we need to be able to do with them along the way.
The other things we need are a "source thing", and a "destination thing". A source thing just needs to provide a data object that can be copied. A destination thing just needs to receive a data object that can be copied.
You confused yourself by trying to mix up the sources and destinations with the data items. If you're going crazy trying to make your class do two contradictory things at once, try breaking it up into two classes that each does one thing.
You never do anything with your SourceDomain Name property, so I won't either. If you need to, I'll leave that as an exercise.
public interface ICopyable<T>
{
void CopyFrom(T other);
}
internal class Program
{
private static void Main(string[] args)
{
var newItem = new SourceDomain<Person>
{
Item = new Person { Age = 11 },
Name = "John"
};
var oldItem = new DestinationDomain<Person>
{
Item = new Person { Age = 10 }
};
//there is an item in a database which is of D1 type. This convertor receives an object S1 in order to update the D1 item.
// the rule is that Sx updatates Dx (where x is 1,2,3,4,5...)
Convertor<Person> convertor = new Convertor<Person>(newItem, oldItem);
var newItem2 = new SourceDomain<Location>()
{
Item = new Location { City = "London" },
Name = "Lynda"
};
var oldItem2 = new DestinationDomain<Location>()
{
Item = new Location { City = "Paris" }
};
Convertor<Location> convertor2 = new Convertor<Location>(newItem2, oldItem2);
Console.ReadKey();
}
}
public class SourceDomain<T>
{
public string Name { get; set; }
public T Item { get; set; }
}
public class DestinationDomain<T> where T : ICopyable<T>, new()
{
public string Name { get; set; }
public T Item { get; set; }
public void CopyItemFrom(T other)
{
if (Item == null)
{
Item = new T();
}
Item.CopyFrom(other);
}
}
// A person is a thing which can turn itself into a copy of another Person.
// You could define a class Wombat : ICopyable<Locomotive>, if you wanted to be
// able to convert Locomotives to Wombats. You'd just add another CopyFrom()
// overload, public void CopyFrom(Locomotive other).
public class Person : ICopyable<Person>
{
public int Age { get; set; }
public void CopyFrom(Person other)
{
Age = other.Age;
}
}
public class Location : ICopyable<Location>
{
public String City { get; set; }
public void CopyFrom(Location other)
{
City = other.City;
}
}
public class Convertor<X> where X : ICopyable<X>, new()
{
protected SourceDomain<X> item;
protected DestinationDomain<X> oldItem;
public Convertor(SourceDomain<X> newObject, DestinationDomain<X> oldObject)
{
item = newObject;
oldItem = oldObject;
//here I want to call, depending of item type, the proper method, not the base one.
//newObject.Data = oldItem.Data;
oldItem.CopyItemFrom(item.Item);
}
}
Homework:
Modify this code so DestinationDomain.CopyItemFrom() receives the source itself, not the source's item.
I think it's better the way I wrote it. Think of reasons why I might have thought that.
Seriously, find out what ref does, and never again use a keyword in your code if you are only guessing about what it might mean. Don't just throw code at the wall, hoping it sticks. You'll get yourself in a lot of frustrating trouble that way.
Finally i have done this:
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
S1 newItem = new S1()
{
Age = 11,
Name = "John"
};
D1 oldItem = new D1()
{
Age = 10
};
//there is an item in a database which is of D1 type. This convertor receives an object S1 in order to update the D1 item.
// the rule is that Sx updatates Dx (where x is 1,2,3,4,5...)
Convertor<S1, D1> convertor = new Convertor<S1, D1>(newItem, oldItem);
S2 newItem2 = new S2()
{
City = "London",
Name = "Lynda"
};
D2 oldItem2 = new D2()
{
City = "Paris"
};
Convertor<S2, D2> convertor2 = new Convertor<S2, D2>(newItem2, oldItem2);
Console.ReadKey();
}
}
public interface ICopyable<T>
{
void CopyFrom(T other);
}
public abstract class SourceDomain
{
public string Name { get; set; }
}
public class S1 : SourceDomain
{
public int Age { get; set; }
}
public class S2 : SourceDomain
{
public string City { get; set; }
}
public class DestinationDomain { }
public class D1 : DestinationDomain, ICopyable<S1>
{
public int Age { get; set; }
public void CopyFrom(S1 other)
{
Console.WriteLine("oldItem.Age " + Age + " new Age; = " + other.Age);
Age = other.Age;
Console.WriteLine("oldItem.Age " + Age + " new Age; = " + other.Age);
}
}
public class D2 : DestinationDomain, ICopyable<S2>
{
public string City { get; set; }
public void CopyFrom(S2 other)
{
City = other.City;
Console.WriteLine(" oldItem.City = City;");
}
}
public class Convertor<X, Y> where X : SourceDomain where Y : DestinationDomain, ICopyable<X>
{
protected X item;
protected Y oldItem;
public Convertor(X newObject, Y oldObject)
{
item = newObject;
oldItem = oldObject;
//here I want to call, depending of X type, the proper method, not the base one.
oldItem.CopyFrom(item);
Console.WriteLine(item);
}
}
}
I have two classes
public class ClassA
{
public int ID { get; set; }
public string Countries {get;set;}
public string City { get;set; }
}
and
public class ClassB
{
public int ID { get; set; }
public string Countries {get;set;}
public string Village{ get;set; }
}
These two classes are in another class
public class ComponentClass
{
public List<ClassA> classAObj { get; set; }
public List<ClassB> classBObj { get; set; }
}
The data for the ComponentClass is coming from third party where the data for ClassA and ClassB is similar in structure. "City" in ClassA will have data in comma separated values "Manchester,Sydney" etc similarly with Village as well with comma separated values.
Now I am building a customized object at business layer where I am iterating through each property of ComponentClass and extracting information.
Main()
{
ComponentClass[] c = //Data from 3rd party;
foreach(var data in c)
{
Parent p = new Parent();
if(data.classAObj.count > 0)
{
Star s = new Star();
s.Area = "infinite";
s.Color = "red";
List<string> sep = data.City.Split(',').Select(string.Parse).ToList();
foreach(var b in sep)
{
TinyStar t = new TinyStar();
t.smallD = b;
s.Values.Add(t);
}
p.Curves.Add(s);
}
if(data.classBObj.count > 0)
{
Star s2 = new Star();
s2.Area = "infinite";
s2.Color = "red";
List<string> sep = data.Village.Split(',').Select(string.Parse).ToList();
foreach(var b in sep)
{
TinyStar t = new TinyStar();
t.smallD = b;
s2.Values.Add(t);
}
p.Curves.Add(s);
}
}
}
In the code above , the two if statements are doing exactly the same operation apart from property names "City" and "Village". I want to simplify this by making use of any design pattern possibly strategy pattern which I just know theoretically or any other patterns.
Here is what I have tried :
public abstract class Base
{
public int ID { get; set; }
public string Countries {get;set;}
}
public class ClassA : Base
{
public string City { get;set; }
}
public class ClassB : Base
{
public string Village{ get;set; }
}
I want to make it as a common factory method which will do the looping and build the object for me for avoiding duplication of the code
public void CommonMethod(Base)
{
// How do I differentiate the properties for looping
}
If the goal is to reduce the code repetition, the two statements could be refactored into a single action as follows.
foreach(var data in c)
{
Parent p = new Parent();
Action<string> iAction = iString =>
{
Star s = new Star();
s.Area = "infinite";
s.Color = "red";
List<string> sep = iString.Split(',').Select(string.Parse).ToList();
foreach(var b in sep)
{
TinyStar t = new TinyStar();
t.smallD = b;
s.Values.Add(t);
}
p.Curves.Add(s);
}
if(data.classAObj.count > 0)
{
iAction(data.City);
}
if(data.classBObj.count > 0)
{
iAction(data.Village);
}
}
You have a same datatype properties for the both of the types in the json than you can create a single class to map it,
public class ClassA
{
public int ID { get; set; }
public string Countries {get;set;}
public string Areas{ get;set; }
}
public class ComponentClass
{
public List<ClassA> classAObj { get; set; }
public List<ClassA> classBObj { get; set; }
}
Main()
{
ComponentClass[] c = //Data from 3rd party;
foreach(var data in c)
{
Parent p = new Parent();
GetParent (p ,data.classAObj )
GetParent (p ,data.classBObj )
}
}
void GetParent (Parent p, ClassA classObj){
if(data.classAObj.count > 0)
{
Star s = new Star();
s.Area = "infinite";
s.Color = "red";
List<string> sep = data.Areas.Split(',').Select(string.Parse).ToList();
foreach(var b in sep)
{
TinyStar t = new TinyStar();
t.smallD = b;
s.Values.Add(t);
}
p.Curves.Add(s);
}
return p ;
}
I would suggest inheriting the ClassA and ClassB from a common base as you did and then casting them, after typechecking. If your only goal is minimizing code-repition this will get your there:
class Program
{
static void Main(string[] args)
{
ComponentClass[] c = new List<ComponentClass>().ToArray();//Data from 3rd party;
foreach (var data in c)
{
Parent p = new Parent();
if (data.classObjs.Count > 0)
{
Star s = new Star
{
Area = "infinite",
Color = "red"
};
foreach (var b in data.classObjs)
{
string bStr = b.GetType() == typeof(ClassA) ? ((ClassA)b).City : ((ClassB)b).Village;
bStr = bStr.Split(',').Select(string.Parse).ToList();
TinyStar t = new TinyStar
{
smallD = bStr
};
s.Values.Add(t);
}
p.Curves.Add(s);
}
}
}
public class ComponentClass
{
public List<ClassObj> classObjs { get; set; }
}
public class ClassObj
{
public int ID { get; set; }
public string Countries { get; set; }
}
public class ClassA : ClassObj
{
public string City { get; set; }
}
public class ClassB : ClassObj
{
public string Village { get; set; }
}
}
It might be necessary to refactor the tenary to if...else or switch depending on if you add more classes of type ClassObj.
Be warned though that GetType actually queries the assembly (at runtime) and should be used with caution from a performance point of view as it can slow down applications a lot when executed often.
I have used reflection, check if it works for you
public static void CommonMethod(dynamic collection)
{
Parent p = new Parent();
Star s = new Star();
s.Area = "infinite";
s.Color = "red";
foreach (var data in collection)
{
var properties = data.GetType().GetProperties();
foreach (var p in properties)
{
string propertytName = p.Name;
var propertyValue = p.GetValue(data, null);
if (propertytName == "City" || propertytName == "Village")
{
List<string> sep = propertyValue.Split(',').ToList();
foreach (var b in sep)
{
TinyStar t = new TinyStar();
t.smallD = b;
s.Values.Add(t);
}
p.Curves.Add(s);
}
}
}
}
static void Main(string[] args)
{
ComponentClass[] c Data from 3rd party;
foreach (var data in c)
{
CommonMethod(data.classAObj);
CommonMethod(data.classBObj);
}
}
I have a list of derived types I want to map to a list of another type. Each derived type maps differently to the new type.
Is there any pattern to do this without casting each types and that keeps the logic of the mapping outside of the type (in a factory).
Here's an example, I'd like to find an alternative to GetFlatSwitch, something like GetFlat :
class Program
{
static void Main(string[] args)
{
List<Base> list = new List<Base>() { new DerivedA() { A = "A" }, new DerivedB() { B = "B" }};
List<Flat> flatList = list.Select(x => Factory.GetFlat(x)).ToList(); // not working
List<Flat> switchFlatList = list.Select(x => Factory.GetFlatSwitch(x)).ToList(); // works, but casting each element
}
static class Factory
{
public static Flat GetFlat(Base baseObj)
{
return new Flat();
}
public static Flat GetFlat(DerivedA a)
{
return new Flat() { A = a.A };
}
public static Flat GetFlat(DerivedB b)
{
return new Flat() { B = b.B };
}
public static Flat GetFlatSwitch(Base baseObj)
{
switch (baseObj.MyType)
{
case MyTypeEnum.A:
DerivedA a = baseObj as DerivedA;
return new Flat() { A = a.A };
case MyTypeEnum.B:
DerivedB b = baseObj as DerivedB;
return new Flat() { B = b.B };
default:
return new Flat();
}
}
}
enum MyTypeEnum
{
A, B
}
abstract class Base
{
public abstract MyTypeEnum MyType { get; }
}
class DerivedA : Base
{
public override MyTypeEnum MyType
{
get
{
return MyTypeEnum.A;
}
}
public string A { get; set; }
}
class DerivedB : Base
{
public override MyTypeEnum MyType
{
get
{
return MyTypeEnum.B;
}
}
public string B { get; set; }
}
class Flat
{
public string A { get; set; }
public string B { get; set; }
}
}
Rather than a design pattern, it seems like you need something like AutoMapper:
AutoMapper is a simple little library built to solve a deceptively
complex problem - getting rid of code that mapped one object to
another. This type of code is rather dreary and boring to write, so
why not invent a tool to do it for us?
Using that library you configure type-to-type mappings so you can call a method to map a type to other type (for example mapper.Map<A, B>(a, b)).
I define two interfaces as following:
public interface IData
{
double value { set; get; }
}
public interface IInterval<C, M>
{
C left { set; get; }
M data { set; get; }
}
Then I use these two interfaces for following class declaration.
public class TESTClass<I, M>
where I : IInterval<int, M>, new()
where M : IData
{
public I interval{ set; get; }
public TESTClass()
{
// This is invalid, cos property value is not visible at initialization ...
interval = new I() { left = 0, data.value = 0 };
// instead I have to do as:
interval = new I() { left = 0 };
interval.data.value = 0;
}
}
am I missing something here ?
I would appreciate if you could help me figure this out.
Well, you could certainly do that. Syntax is bit different.
public TESTClass()
{
interval = new I()
{
left = 0,
data = //Reads data property,
{
value = 0 //set data.value to 0
}
}
}
You can't access sub-properties in object initializers using the member-access operator (.).
This works:
public class TESTClass<I, M>
where I : IInterval<int, M>, new()
where M : IData, new()
{
public I interval{ set; get; }
public TESTClass()
{
interval = new I() { left = 0, data = new M {value = 0} };
}
}