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

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

Related

Confusion over using abstract class in c#

I have a question since I'm new in programming Im really confused about how to implement a best practice solution for the following problem, Its a game logic,here are the possible ways of making points
EnemyA 400,
EnemyB 500,
EnemyC 700,
Coin 200,
FireBall 300
means hitting Coin gives you 200 points and shooting FireBall gives you 300 &...
if you reach 1000 points you will get an extra life, the logic simple but implementing the best practice is not(at least to me)should I use abstract class or Dictionary?
So far, I used a Dictionary, I read a given file (txt) file which is written (EnemyA,EnemyB,Coin,Coin,Coin,Coin) then I calculate the points:
public int pointCal(IEnumerable<string> enemyType)
{
var possiblePoints = new Dictionary< EnemisEntity,int>()
{
{new EnemisEntity{enemyType="EnemyA"},400 },
{new EnemisEntity{enemyType="EnemyB" },500 },
{new EnemisEntity{enemyType="EnemyC"},700 },
{new EnemisEntity{enemyType="Fireball"},300 },
{new EnemisEntity{enemyType="Coin"},200 },
};
int z=0;
List<int> myPoints=new List<int> ();
foreach (var item in enemyType)
{
z = possiblePoints.FirstOrDefault(f => f.Key.enemyType.Equals(item)).Value;
myPoints.Add(z);
}
int finalPonts= g.Sum(s=>Convert.ToInt32(s));
return finalPonts;
}
Enemy entity class:
public class EnemisEntity
{
public string enemyType { get; set; }
}
It depends. Are the enemies different types of objects (with different properties and such)?
Then it might make sense to create an abstract class and child classes.
public abstract class Shootable {
public int points;
}
public class EnemyA: Shootable {
}
public class EnemyB: Shootable {
}
public class Coin: Shootable {
}
// etc
If all your items are just shootable with one description, then
public class Shootable {
public int points { get; set; }
public string enemyType { get; set; }
public Shootable(int points, string enemyType ){
this.points = points;
this.enemyType = enemyType;
}
}
// then create like
var coin = new Shootable(500, "coin");
If all enemies can be modeled in the same class, then you only need shootable class
Then get the points:
IEnumerble<Shootable> shootableItems = GetShootableFromFile();
var score = shootableItems.Sum(s => s.Points);
You GetShootableFromFile should create one object per file row. So it is a viable situation to create the same objects twice:
// This is a mock to indicate multiple instances of the same class.
public IEnumerble<Shootable> GetShootableFromFile() {
List<Shootable> shootable = new List<Shootable>();
shootable.Add(new Shootable(500,"coin"));
shootable.Add(new Shootable(500,"coin"));
shootable.Add(new Shootable(500,"coin"));
shootable.Add(new Shootable(300,"enemyA"));
shootable.Add(new Shootable(300,"enemyB"));
// etc
}
To me, this is a question of design. When the only difference between enemies is just the value of points as well as their name it is not a good idea to define a class hierarchy. The only thing different between a EnemyA and a EnemyB class would be just the values contained within each class. So you can use a single common class to hold information for each enemy and process the points.
Below is the simplest working prototype that I could code that implements this design. It relies on two classes. The EnemyEntity class to hold the type of enemy and its points, and a Game class that contains the logic behind scoring and keeping a record of all possible enemies.
public class EnemyEntity
{
public EnemyEntity(string type, int points)
{
Type=type;
Points=points;
}
public string Type { get; }
public int Points { get; }
}
public class Game
{
public Game(params (string type, int points)[] values)
{
this.Enemies = new List<EnemyEntity>();
foreach (var (type, points) in values)
{
Enemies.Add(new EnemyEntity(type, points));
}
}
public List<EnemyEntity> Enemies { get; }
public int CalculatePoints(IEnumerable<string> targets)
{
int points = 0;
foreach (var item in targets)
{
var target = Enemies.FirstOrDefault((enemy) => enemy.Type.Equals(item));
if (target!=null)
{
points+= target.Points;
}
}
return points;
}
}
class Program
{
static void Main(string[] args)
{
var game = new Game(
("EnemyA", 400),
("EnemyB", 500),
("EnemyC", 700),
("Coin", 200),
("FireBall", 300));
var input = "EnemyA,EnemyB,Coin,Coin,Coin,Coin";
var targets = input.Split(',');
var points = game.CalculatePoints(targets);
Console.WriteLine(points);
// 1700
}
}
NOTES:
The simplest approach is to use a List<EnemyEntity> and do the lookup with .FirstOrDefault(). I could use a Dictionary<string,EnemyEntity> which would simplify the lookup process. Here is how the Game class would change using a dictionary.
public class Game
{
public Game(params (string type, int points)[] values)
{
this.Enemies = new Dictionary<string, EnemyEntity>();
foreach (var (type, points) in values)
{
Enemies[type] = new EnemyEntity(type, points);
}
}
public Dictionary<string, EnemyEntity> Enemies { get; }
public int CalculatePoints(IEnumerable<string> targets)
{
int points = 0;
foreach (var item in targets)
{
var target = Enemies[item];
if (target!=null)
{
points+= target.Points;
}
}
return points;
}
}

Assign bool value to a property when name of that property is present in another array

This is best I could make the question statement. Please be kind.
Here is the situation:
I have a string "InputValues" which contains values in comma seperated format:
chkAwareness1,chkAwareness2,chkAwareness6,chkAwareness9,chkAwareness13...
I need to fill an object with bool value if the name matches with what I have in above string variable.
example:
if InputValues contains "chkAwareness1" then "public bool chkAwareness1" should set to true, otherwise false.
public class SurveyCheckBox
{
public bool chkAwareness1 { get; set; }
public bool chkAwareness2 { get; set; }
public bool chkAwareness3 { get; set; }
public bool chkAwareness4 { get; set; }
public bool chkAwareness5 { get; set; }
public bool chkAwareness6 { get; set; }
public bool chkAwareness7 { get; set; }
.
.
.
}
public void createObjectSurveyCheckBox(string InputValues)
{
string[] ChkValues = InputValues.Split(',');
SurveyCheckBox surveyChkBoxObj = new SurveyCheckBox();
for (int i = 0; i < NumberOfPropertyInSurveyCheckBox ;i++ )
{
// typeof(SurveyCheckBox).GetProperties()[i].Name
}
}
I searched and I found GetProperties method through which I can get the name of property, but I am unable to figure out the logic.. how to search through the values and assign them to bool properties.
Please help.
You're very close. You just need to change your loop, really. The whole method should look like this:
public void CreateObjectSurveyCheckBox(string inputValues)
{
string[] chkValues = inputValues.Split(',');
SurveyCheckBox surveyChkBoxObj = new SurveyCheckBox();
foreach (string value in chkValues)
{
PropertyInfo propInfo = typeof(SurveyCheckBox).GetProperty(value);
if (propInfo != null)
propInfo.SetValue(surveyChkBoxObj, true);
}
}
P.S. You'll notice I took the liberty of changing your capitalization to something much more standard. If you use capitalization like you had, you're likely to get lynched.
I agree with Tim; I would not use something like this in production code.
public void createObjectSurveyCheckBox(string InputValues)
{
var instance = new SurveyCheckBox();
foreach (var property in typeof(SurveyCheckBox).GetProperties().Where(x => x.Name.Contains("chkAwareness")))
{
if (InputValues.Contains(property.Name))
property.SetValue(instance, true);
}
}
I would write the loop from the other direction, from 0 to MaxchkAwareness;
Sort the input first, before going into the loop.
You would also need an index to the next item in your input array (ChkValues), lets call that chkValueIndex;
If the next item in your input array, ChkValues[chkValueIndex], is "chkAwareness"+i.ToString()
then your property is true, and you increment your array pointer .
otherwise your property is false.
But I think you have to use reflection to set the properties in a loop like that, something like this:
Getting a property reference using reflection
I am sure there are better ways to restructure this and do it entirely different, but it sounds to me like you are trying to do the best you can with the system that was given you.
You can try this:
public static void createObjectSurveyCheckBox(string InputValues)
{
string[] ChkValues = InputValues.Split(',');
SurveyCheckBox surveyChkBoxObj = new SurveyCheckBox();
foreach (var prop in typeof(SurveyCheckBox).GetProperties())
{
if (ChkValues.Contains(prop.Name))
prop.SetValue(surveyChkBoxObj, true);
}
}

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

Enumeration Objects (Strings) in Entity Framework

I am building a model with Entity Framework and purchased responsive CSS.
The built in fixed icons comes with CSS. Like as follows (Name and Icon Class Value)
I need a way to keep the names of icons as fixed enums to access it from the VS intellisense. Currently we can't store as a entity table in entity framework (as it require relationship with tables difficult to maintain) and enum doesn't allows string type.
Code that did not work:
public sealed class IconType
{
public static readonly IconType Rupee_Icon = new IconType("rupee-icons");
public static readonly IconType Doller_Icon = new IconType("doller-icon");
private IconType(int EnumID,string EnumObjectValue)
{
IconValue = EnumObjectValue;
}
public string IconValue { get; private set; }
}
More code that did not work (CSS class names contains whitespaces like ui bell icon):
public enum Icon
{
NotSet=0,
Idea Icon=1,
Bell Icon =2
}
Is there any other ways to use names / objects as enums or constants in EF for easy intellisense in Visual Studio?
You could:
Omit the white spaces in the enums:
public enum Icon
{
NotSet = 0,
IdeaIcon = 1,
BellIcon = 2
}
Add a description or name (Or even some custom attribute) attributes to the enums:
public enum Icon
{
NotSet = 0,
[Description("ui idea icon")]
IdeaIcon = 1,
[Description("ui bell icon")]
BellIcon = 2
}
When needed get the description name. Example method to get the description attribute value:
public static string GetDescription<T>(this T enumerationValue)
where T : struct, IConvertible
{
var type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
}
// Tries to find a DescriptionAttribute for a potential friendly name for the enum
var memberInfo = type.GetMember(enumerationValue.ToString(CultureInfo.InvariantCulture));
if (memberInfo.Length > 0)
{
var attributes = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
// Pull out the description value
return ((DescriptionAttribute)attributes[0]).Description;
}
}
// If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString(CultureInfo.InvariantCulture);
}
Did you consider using string constants?
public static class IconType
{
public const string RUPEE_ICON = "rupee-icon";
public const string DOLLER_ICON = "doller-icon";
// ...
}
Store the icon's as plain old objects. Why make use of entity framework at all?
public static class Icons
{
public enum Type
{
IdeaIcon = 1,
BellIcon =2
}
public static Icon Get(Type type)
{
return IconCollection.Single(icon => icon.Type == type);
}
static IEnumerable<Icon> IconCollection
{
get
{
return new List<Icon>
{
new Icon(Type.IdeaIcon, "Idea Icon", "icon idea-icon"),
new Icon(Type.BellIcon, "Bell Icon", "icon bell-icon"),
};
}
}
public class Icon
{
public Icon(Type type, string description, string cssClass)
{
Type = type;
Description = description;
CssClass = cssClass;
}
public Type Type { get; private set; }
public string Description { get; private set; }
public string CssClass { get; private set; }
}
}
Use in code:
public class Class1
{
public void Method1()
{
var ideaIcon = Icons.Get(Icons.Type.IdeaIcon);
var x = ideaIcon.CssClass;
var y = ideaIcon.Description;
var bellIcon = Icons.Get(Icons.Type.BellIcon);
// etc...
}
}
Razor view:
#Icons.Get(Icons.Type.BellIcon).CssClass
If you needed to enumerate over the icon collection you could easily add another static accessor to the Icons class.

c# access child class from parent

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

Categories