c# access child class from parent - c#

I have two classes. Jewellery is base and Ring inherits from it.
class Jewellery
{
public string Name { get; set; }
......
public Jewellery(string name)
{
Name = name;
}
}
.
class Ring : Jewellery
{
public string Size { get; set; }
public Ring(string name, string size) :base(name)
{
Size = size
}
}
Now in main i created List of Jewellery and in that list i added Ring object.
Ring ring = new Ring("Diamond", "Very big");
List<Jewellery> jewellery = new List<Jewellery>();
jewellery.Add(ring);
Now when debugging i can access ring object from jewellery list. Can i do it from code? I think this should be done like this, but this doesn't work.
jewellery[0].Ring

You need to cast it, e.g.:
var myRing = (Ring)jewellery[0];
or
var maybeRing = jewellery[0] as Ring;
if (maybeRing != null)
{
// do stuff
}
or
if (jewellery[0] is Ring)
{
// Cast and do stuff
}
For multiple types you can
if (jewellery[0] is Ring)
{
// Cast and do stuff
}
else if(jewllery[0] is Necklace)
{
// and so on
}
See MSDN on safe casting.
Depending on what you want to do you can use Linq to filter by type:
Given:
List<Jewellery> things = new List<Jewllery>();
Then:
public IList<T> GetJewellery<T>(this jewellery) where T : Jewellery
{
return jewellery.OfType<T>().ToList();
}
Can:
IList<Necklace> necklaces = things.GetJewellery<Necklace>();
IList<Ring> rings = things.GetJewellery<Ring>();

Related

Get values out of collections with FastMember

I use FastMember to get values out of objects and nested objects. If a property is a string or int everything works fine. But now I want to get the values also for collections. Here is my code so far:
// Set accessor
var sourceAccessor = ObjectAccessor.Create(source);
if (sourceAccessor.Target.GetType().GetInterface(nameof(ICollection)) != null || sourceAccessor.Target.GetType().GetInterface(nameof(IEnumerable)) != null)
{
foreach (/* idk */)
{
// READ & RETURN VALUES HERE
}
}
An object could look like this:
{
Id: 1,
Surname: Doe,
Prename: John,
Professions: [
{ Name: ab },
{ Name: xy }
]
}
Which means professions would result in a problem.
Any advise how I can solve this problem? Thanks!
It's not obvious from the question what the data type of the source variable is, but you should just be able to check if the value returned by the accessor implements IEnumerable or not and act accordingly.
Here's a quick worked example that iterates over the Professions property of a 'Person' object and just dumps the ToString() representation to the console - if you wanted to dive into each Profession object using FastMember you could construct another ObjectAccessor to do it, I guess - it's not clear what your goal is once you're iterating.
The same tactic will work if you're building the ObjectAccessor directly from an array - you just check if the accessor.Target is IEnumerable and cast-and-iterate in a similar fashion.
class Program
{
static void Main(string[] args)
{
var p = new Person
{
Professions = new List<Profession>
{
new Profession("Joker"),
new Profession("Smoker"),
new Profession("Midnight toker")
}
};
var accessor = ObjectAccessor.Create(p);
var professions = accessor[nameof(Person.Professions)];
if (professions is IEnumerable)
{
foreach (var profession in (IEnumerable)professions)
{
Console.WriteLine(profession);
}
}
}
}
class Person
{
public List<Profession> Professions { get; set; }
}
class Profession
{
public string Name { get; set; }
public Profession( string name)
{
Name = name;
}
public override string ToString()
{
return Name;
}
}

Add all item from ObservableCollection to field another ObservableCollection(Different class)

I have two ObversableCollection:
public ObservableCollection<SearchIDResult> _Found;
public ObservableCollection<Clip> _clipsFound;
Classes Clip and SearchIDResult
public class SearchIDResult
{
Clip Clip;
string Property;
SearchIDResult(Clip AddedClip)
{
Clip = AddedClip;
}
}
public class Clip
{
public string ID { get; set; }
public string Title { get; set; }
}
I want to add all items from _clipsFound collection to _Found collection to field Clip of class SearchIDResult.
Something like this:
foreach (Clip clip in _clipsFound)
{
SearchIDResult var = new SearchIDResult(clip);
_Found.Add(var);
}
How can I do it?
It seems you forget the new keyword, try this please:
SearchIDResult var = new SearchIDResult(clip);
_Found.Add(var);
Also... var is a C# language keyword, although apparantly legal to use as a variable name, in general I would not recommend doing so.
Alternative (replaces both lines):
_Found.Add(new SearchIDResult(clip));
I just need public constructor. Trouble was been here
public class SearchIDResult
{
Clip Clip;
string Property;
public SearchIDResult(Clip AddedClip)
{
Clip = AddedClip;
}
}

Serialize list of objects

I need to serialize/deserialize some XML code and part of it looks like next example:
<CoordGeom>
<Curve rot="cw" chord="830.754618036885" crvType="arc" delta="72.796763873948" dirEnd="283.177582669379" dirStart="355.974346543327" external="169.661846548051" length="889.38025007632" midOrd="136.562611151675" radius="699.999999998612" tangent="516.053996536113">
<Start>4897794.2800513292 6491234.9390137056</Start>
<Center>4897096.0071489429 6491185.7968343571</Center>
<End>4897255.5861026254 6491867.3645547926</End>
<PI>4897758.0514541129 6491749.7197593488</PI>
</Curve>
<Spiral length="109.418078418008" radiusEnd="INF" radiusStart="699.999999999025" rot="cw" spiType="clothoid" theta="4.477995782709" totalY="2.849307921907" totalX="109.351261203955" tanLong="72.968738862921" tanShort="36.493923980983">
<Start>4897255.5861026254 6491867.3645547936</Start>
<PI>4897220.0531303799 6491875.6840722272</PI>
<End>4897147.9238984985 6491886.7208634559</End>
</Spiral>
<Spiral length="153.185309785019" radiusEnd="499.99999999993" radiusStart="INF" rot="ccw" spiType="clothoid" theta="8.776871734087" totalY="7.808812331497" totalX="152.826239431476" tanLong="102.249348442205" tanShort="51.176160975293">
<Start>4897147.9238985004 6491886.7208634559</Start>
<PI>4897046.8509311257 6491902.186455016</PI>
<End>4896998.0370401107 6491917.5553683294</End>
</Spiral>
<Curve rot="ccw" chord="936.510896488672" crvType="arc" delta="138.94725576785" dirEnd="66.423714388543" dirStart="287.476458620693" external="925.970149937768" length="1212.543549877849" midOrd="324.680762068264" radius="499.999999999181" tangent="1335.436583485725">
<Start>4896998.0370401107 6491917.5553683294</Start>
<Center>4897148.1939981515 6492394.4755796343</Center>
<End>4896948.2091376046 6492852.7397562303</End>
<PI>4895724.243644949 6492318.6055583945</PI>
</Curve>
</CoordGeom>
I've generated automatically classes using xsd.exe. Part of generated code looks like this:
public partial class CoordGeom
{
private List<object> _items;
private List<Feature> _feature;
private string _desc;
private string _name;
private stateType _state;
private string _oID;
public CoordGeom()
{
_feature = new List<Feature>();
_items = new List<object>();
}
[XmlElementAttribute("Chain", typeof(Chain))]
[XmlElementAttribute("Curve", typeof(Curve))]
[XmlElementAttribute("IrregularLine", typeof(IrregularLine))]
[XmlElementAttribute("Line", typeof(Line))]
[XmlElementAttribute("Spiral", typeof(Spiral))]
public List<object> Items
{
get { return this._items; }
set { this._items = value; }
}
[XmlElement("Feature")]
public List<Feature> Feature { get; set; }
[XmlAttribute()]
public string desc { get; set; }
[XmlAttribute()]
public string name { get; set; }
[XmlAttribute()]
public stateType state { get; set; }
[System.Xml.Serialization.XmlAttributeAttribute()]
public string oID
{
get{ return this._oID; }
set{ this._oID = value; }
}
}
And my code for deserialization look like this:
XmlSerializer mySerializer = new XmlSerializer(typeof(LandXML), new XmlRootAttribute(""));
TextReader myFileStream = new StreamReader("myFile.xml");
LandXML myObject = (LandXML)mySerializer.Deserialize(myFileStream);
var coordGeomItems = myObject.Alignments.Alignment[0].CoordGeom;
My problem is that, when I deserialize file, it is deserialized as list of items of type {LandXML.Curve}, {LandXML.Spiral} etc. and I don't know how to access their properties. It would be great if I can do this directly. Here is a screenshot:
EDIT 1
Here is inital screen
then I have items:
When I unfold this
And this is at the top layer of object - it has some InnerXml, InnerText... If I want to achieve CoordGeom, there is a lot object.Item(i).ChildNodes.Item(j).ChildNodes...
And all of that is because in some lines, lists of objects are made like List as for CoordGeom
Because there are multiple allowed types, the Items collection is typed as object. The simplest approach is to enumerate and cast each item:
foreach(var item in coordGeomItems.Items)
{
var curve = item as Curve;
if (curve != null)
{
// access curve properties here
}
var spiral = item as Spiral
if (spiral != null)
{
// access spiral properties here
}
// ...
}
You could build up a list of Curves and Spirals and access them using properties with custom getters:
class CoordGeom
{
public List<object> Items;
List<Curve> _curves;
public List<Curve> Curves
{
get
{
return _curves ?? (_curves = Items
.Where(item => item is Curve).Select(curve => (Curve)curve).ToList());
}
}
}
The null coalescing operator (??) will cause the Curves property to set and return the value of _curves as a list of curves if _curves is null. This basically causes it to initialize the list on the first get and on all subsequent gets it will return the already initialized list.
As you cannot change the generated class nor the XML.The best possible approach would be to write an extension method.
public static List<Curve> GetCurves(this CoordGeom cg)
{
return cg.Items.OfType<Curve>().ToList();
}
public static List<Spiral> GetSpirals(this CoordGeom cg)
{
return cg.Items.OfType<Spiral>().ToList();
}
Once you do this, you can get items like this
var coordGeomItems = myObject.Alignments.Alignment[0].CoordGeom;
var curves = coordGeomItems.GetCurves();
var spirals = coordGeomItems.GetSpirals();

How To get one list from a Generic list which contains difrent type of class, simply

I am testing a simple code block to be used in my project.Firsly I want to give example. Here is the class
class Processing
{
public string Region { get; set; }
public Car _car {get;set;}
public double Kilometer { get; set; }
}
class Car
{
public string LicansePlate { get; set; }
public string Driver { get; set; }
public double OdoMeter { get; set; }
}
Now. I have created List of Processing.This list contatin:
String Region
Car _car
double Kilometer
I want to make list flatten using SelectMany() simply. Why I am using this way is SelectMany() will take "var" as referance in future.My Target outpur is like that :
Region LicancePlate Driver Odometer Kilometer
... ... ... ... ...
... ... ... ... ...
This code block is only test.Main Block is like that.
public partial class MainWindow : Window
{
List<Processing> proces;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
proces= new List<Processing>(){
new Processing {Region="Konya",Kilometer=96,_car= new Car(){LicansePlate="34 ABR 45", Driver="Hasan Doğan", OdoMeter=1322}},
new Processing {Region="Karaman",Kilometer=233,_car=new Car{ LicansePlate="34 JT 9809" ,Driver="Ahmet Turgut",OdoMeter=1231}},
new Processing { Region = "Ankara", Kilometer = 57, _car=new Car {LicansePlate = "34 JK 8547", Driver = "Tuncay Yıldız", OdoMeter = 472 }}
};
var kk = proces.SelectMany(b => b);
dtgrid.ItemsSource = kk.ToList();
}
var kk = kullanımlar.SelectMany(b => b); sentences give error.How to get all rows with sub field using SelectMany().Error is following :
cannot be inferred from the usage. Try specifying the type arguments explicitly.
It looks like you want Select instead of SelectMany:
var kk = proces.Select(p => new {
Region = p.Region,
LicencePlate = p.c.LicencePlate,
Driver = p.c.Driver,
Odometer = p.c.Odometer,
Kilometer = p.Kilometer
});
If you want a "plane" list then you have to iterate properties.
you can do like this for example
write a recursive func that iterates proces[0] properties
proces[0].getType().GetProperties()
could do getting properties...
when iteration gets a propertiy push in a Expando or something like then you there
you have a DYNAMIC FLAT list :)
In turkish, liste ne olursa olsun grid benzeri bir liste için propertiler içerisindeki classları da bir döngüyle alıp expando obje içine bas.. olay biter ;)
kolaylıklar diliyorum... Take it easy...

How to read the properties of an object inside an arraylist

I'm having some issues reading the properties of an item I have placed into an arraylist and I can't find the answer anywhere.
ArrayList itemsArrayList = new ArrayList();
itemsArrayList.Add(abyssalScepter);
itemsArrayList.Add(aegisOfTheLegion);
itemInBuildAbilityPower = itemsArrayList[0].abilityPower;
I need to be able to read the properties of the objects in the array so I can apply their values elsewhere but this gets me nowhere.
You need to cast object to the expected type (and hope it's really of this type).
itemInBuildAbilityPower = ((Item)itemsArrayList[0]).abilityPower;
The better option (if the infrastructure code is yours) to use generic container, e.g. List<T>.
List<Item> itemsArrayList = new List<Item>
itemsArrayList.Add(abyssalScepter);
itemsArrayList.Add(aegisOfTheLegion);
itemInBuildAbilityPower = itemsArrayList[0].abilityPower;
try
var itemInBuildAbilityPower = itemsArrayList[0].GetType().GetProperty ("abilityPower").GetGetMethod().Invoke (itemsArrayList[0], null);
Building on elder_george's answer, here is an example of what you could do if abyssalScepter and aegisOfTheLegion are not the exact same type:
using System.Collections.Generic;
class Power { }
interface IAbilityPower { Power abilityPower { get; set; } }
class Scepter : IAbilityPower { public Power abilityPower { get; set; } }
class Aegis : IAbilityPower { public Power abilityPower { get; set; } }
class Test
{
public static void Main()
{
var abyssalScepter = new Scepter();
var aegisOfTheLegion = new Aegis();
var itemsList = new List<IAbilityPower>();
itemsList.Add(abyssalScepter);
itemsList.Add(aegisOfTheLegion);
var power = itemsList[0].abilityPower;
}
}

Categories