Dynamically creating and calling a class using Reflection in a console application - c#

I have some problems about this section in C# language.
So I'm trying to do something like revealing reflection of this class and it's methods.
class Car
{
public string Name { get; set; }
public int Shifts{ get; set; }
public Car(string name, int shifts)
{
Name = name;
Shifts = shifts;
}
public string GetCarInfo()
{
return "Car " + Name + " has number of shifts: " + Shifts;
}
}
So I have this class Car, and this method GetCarInfo(), now, I'm trying to:
Dynamically create instance of this class Car, and dynamically calling a method GetCarInfo(), I would like to show result in console, but I can't when I run it it shows build errors. The application break every time.
Edit
Errors

Here's a example
namespace ConsoltedeTEstes
{
class Program
{
static void Main(string[] args)
{
//Get the type of the car, be careful with the full name of class
Type t = Type.GetType("ConsoltedeTEstes.Car");
//Create a new object passing the parameters
var dynamicCar = Activator.CreateInstance(t, "User", 2);
//Get the method you want
var method = ((object)dynamicCar).GetType().GetMethod("GetCarInfo");
//Get the value of the method
var returnOfMethod = method.Invoke(dynamicCar, new string[0]);
Console.ReadKey();
}
}
public class Car
{
public string Name { get; set; }
public int Shifts { get; set; }
public Car(string name, int shifts)
{
Name = name;
Shifts = shifts;
}
public string GetCarInfo()
{
return "Car " + Name + " has number of shifts: " + Shifts;
}
}
}

Related

C# Refer to a Specific Item in a List<Custom Class>

I created a class of collectables. The class contains a string Name, int Points and int Damage. I created a Collectable instance called "lifeforce" "Life Force" is the Name and Points is set with a value of 1000. When a separate class of immortals is instantiated I add a Collectable instance to a List to the immortal. If I want to see how many points the immortal instance has for his/her Life Force, how do I refer to the lifeforce Points to get the value? Code below.
public class Collectable
{
public string Name { get; set; }
public int Points { get; set; }
public int Damage { get; set; }
public Collectable(string name, int points, int damage)
{
Name = name;
Points = points;
Damage = damage;
}
}
public class Immortal
{
public string Name { get; set; }
public string Origin { get; set; }
public string Superpower { get; set; }
public List<Collectable> Carrying { get; set; }
public string Saying { get; set; }
public string Bent { get; set; }
public Immortal(string name, string origin, string superpower, string saying, string bent, Collectable item)
{
Name = name;
Origin = origin;
Superpower = superpower;
Saying = saying;
Bent = bent;
this.Carrying = new List<Collectable>();
this.Carrying.Add(item);
}
public void Pickup(Collectable item)
{
this.Carrying.Add(item);
}
}
static void Main(string[] args)
{
Collectable lifeforce = new Collectable("Life Force", 1000, 0);
Collectable rubystone = new Collectable("Ruby Stone", 200, 0);
Collectable bagofdiamonds = new Collectable("Diamond Bag", 500, 0);
Immortal mighty = new Immortal("Mighty Man", "Mightopolis", "Might", "I am a mighty man!", "good",lifeforce);
foreach (var collecteditem in mighty.Carrying)
{
Console.WriteLine("Items in bag - " + collecteditem.Name);
}
var lifeforceIndx = 0;
lifeforceIndx = mighty.Carrying[0].Points
Console.WriteLine("Your Life Force is at " + mighty.Carrying[0].Points.ToString());
Console.ReadLine();
}
You can do :
Console.WriteLine("Your Life Force is at " + mighty.Carrying.Where(x=>x.Name == "Life Force").Sum(x=>x.Points).ToString());
To find all Collectables named "Life Force" just use
Carrying.Where(collectable => string.Equals(collectable.Name, "Life Force", StringComparison.OrdinalIgnoreCase));
Ignore case is necessary for cases when Name property has different spelling.
But I recommend to create Enum with collectable types and use this Enum in Collectable class.
For example
public class Collectable
{
public string Name { get; set; }
public int Points { get; set; }
public int Damage { get; set; }
public CollectableType Type { get; }
public Collectable(string name, int points,
int damage, CollectableType type)
{
Name = name;
Points = points;
Damage = damage;
Type = type;
}
}
And find all Life Force collectables like shown in code below
Collectables.Where(collectable => collectable.Type == CollectableType.LifeForce);
If you need sum of points than just add .Sum(collectable => collectable.Points) to get
Collectables.Where(collectable => collectable.Type == CollectableType.LifeForce)
.Sum(collectable => collectable.Points);
If I get it right then this is the solution.

Does not contain constructor & Non-invocable member Class C#

I'm trying to create a simple class by referring to a YouTube video, but I get errors.
Here are the errors:
And here is my code:
public class Student
{
public int stdAge;
public int stdiD;
public string stdCitizenship;
public void printStudent()
{
Console.WriteLine("Student Age: " + stdAge);
Console.WriteLine("Student ID: " + stdiD);
Console.WriteLine("Student Citizenship:" + stdCitizenship);
}
}
class Program
{
static void Main(string[] args)
{
Student std1 = new Student("Roslin Hashim");
std1.stdAge(26);
std1.stdiD(520308);
std1.stdCitizenship("Malaysia");
std1.printStudent();
}
}
How do I know what the problem is and how to fix it?
You're not setting your values properly. I assume you were trying to set stdAge, stdiD and stdCitizenship by doing the following:
std1.stdAge(26);
std1.stdiD(520308);
std1.stdCitizenship("Malaysia");
You're using them like functions when they are not. You need to put getters and setters on stdAge, stdiD and stdCitizenship and then set them using a simple = sign. You also did not create a constructor that takes in 1 string argument. So you'll need to do that. The following code should do what you're trying to do.
public class Student
{
//Setting getter and setters
public int stdAge { get; set; }
public int stdiD { get; set; }
public string stdCitizenship { get; set; }
//Here's the constructor you need
public Student(string name) {
//Code to do sometihng with name parameter here.
}
public void printStudent()
{
Console.WriteLine("Student Age: " + stdAge);
Console.WriteLine("Student ID: " + stdiD);
Console.WriteLine("Student Citizenship:" + stdCitizenship);
}
}
class Program
{
static void Main(string[] args)
{
Student std1 = new Student("Roslin Hashim");
std1.stdAge = 26;
std1.stdiD = 520308;
std1.stdCitizenship = "Malaysia";
std1.printStudent();
}
}

Winforms combobox displaying class names instead of actual object name

I have this class that contains a static list
public class TypeList
{
public string Name;
public string NameTag;
public TypeList(string Name, string NameTag)
{
this.Name = Name;
this.NameTag = NameTag;
}
public static List<TypeList> DataType = new List<TypeList>() {
new TypeList("DataType","-1"),
new TypeList("OpOne","1"),
new TypeList("OpTwo","2"),
};
}
I then put the static list called DataType into a combobox:
public void RefreshList()
{
List<TypeList> data = new List<TypeList>();
data = TypeList.DataType;
typeCB.DataSource = data;
typeCB.DisplayMember = "Name";
typeCB.ValueMember = "NameTag";
typeCB.SelectedValue = -1;
typeCB.SelectedText = "Select DataType";
}
However, when I run it, all I get are the classnames in my combobox. Is something wrong with my code? I tried to do
data.Select(x=>x.Name).ToList()
But that just gives me the name portion.
I might be wrong, but based on the Documentation and Example it might be that this Feature only works with public property getters, not public fields:
Gets or sets the property to display for this ListControl.
public class USState
{
private string myShortName;
private string myLongName;
public USState(string strLongName, string strShortName)
{
this.myShortName = strShortName;
this.myLongName = strLongName;
}
public string ShortName
{
get
{
return myShortName;
}
}
public string LongName
{
get
{
return myLongName;
}
}
}
Of course I would also advise against making the list a part of the Type class. A simple Programm scope static would be better. If that is the case and as autoproties have have become a thing by now, this should be enough of a fix:
public class Type
{
public string Name { private set; get } ;
public string NameTag {private set; get };
public TypeList(string Name, string NameTag)
{
this.Name = Name;
this.NameTag = NameTag;
}
}
//use in the class of main, the form or some similar central point
static List<Type> TypeList = new List<Type>();

Missing parameterless constructor when casting Jil dynamic deserialized object array

In our application we have a problem using a dynamic object, that is the result of JSON deserialization with Jil. The following code is just to show the problem.
void Main()
{
var modelJson = "{\"Id\":1,\"Options\":[{\"Id\":2,\"Name\":\"Option 1\"}]}";
var modelDto = Jil.JSON.DeserializeDynamic(modelJson);
var options = modelDto.Options;
var optionsIEnumerable = (IEnumerable<Option>)options;
var optionsArray1 = optionsIEnumerable.ToArray();
var optionsArray2 = optionsIEnumerable.Cast<Option>().ToArray();
}
class Model
{
public Model(long id, IEnumerable<Option> options = null)
: this()
{
this.Id = id;
this.Options = options;
}
private Model() => this.Options = new List<Option>();
public long Id { get; }
public IEnumerable<Option> Options { get; }
}
class Option
{
public Option(long id, string name)
{
this.Id = id;
this.Name = name;
}
private Option()
{
}
public long Id { get; private set; }
public string Name { get; private set; }
}
The last two lines in Main both cause a MissingMethodException, saying there is no parameterless constructor. But both Model and Option have a parameterless constructor (and I am not even using Model at this point).
How can I cast the property modelDto.Options into a Option[]?
This is not the exact answer to your question but you could easily deserialize this JSON with the model.
static void Main(string[] args)
{
var modelJson = "{\"Id\":1,\"Options\":[{\"Id\":2,\"Name\":\"Option 1\"}]}";
var modelDto = Jil.JSON.Deserialize<ModelNew>(modelJson);
ShowObject(modelDto);
Console.Read();
}
class ModelNew
{
public int Id { get; set; }
public Option[] Options { get; set; }
public ModelNew() {}
}
class Option
{
public long Id { get; private set; }
public string Name { get; private set; }
private Option() {}
}
Edit:
To see the object use this function:
static void ShowObject(ModelNew obj)
{
Console.WriteLine("Id: " + obj.Id);
foreach (var op in obj.Options)
{
Console.WriteLine("Id: " + op.Id);
Console.WriteLine("Name: " + op.Name);
}
}
Output:
Id: 1
Id: 2
Name: Option 1

c# field with 'properties'

First of all I was unsure how to name this topic. I want to have a class with fields, and I would like to have some of them to have some Properties, Fields. Maybe I will show some of my code and explain it a bit.
class Column
{
public string Source { }
public string Destination { }
}
I want both "Source" and "Destination" to have inside them more 'fields'. For example "Name", "Type" etc.
I will read some text like:
Source home(1) type[3] Destination NewYork(3) Seattle[2]
I would like to be able to distinguish which part of my text to put inside "Source" and which inside "Destination". How should I do it?
I know that it may not be 100% clear, but I did my best to write it as simple as possible.
You need to define types and return those from those properties:
public class Column
{
private Source _Source = new Source();
private Destination _Destination = new Destination();
public Source Source { get { return _Source; } }
public Destination Destination { get { return _Destination; } }
}
public class Source
{
public string Name { get; set; }
public string Type { get; set; }
}
public class Destination
{
public string Name { get; set; }
public string Type { get; set; }
}
I want both "Source" and "Destination" to have inside them more 'fields'
You cannot do it like this as you have specified that they have type string.
If you feel that they should have some fields in them then consider making them objects like
public class Source
{
public string Name{get;set;}
public string Type{get;set;}
}
then you can edit your column class like this
public class Column
{
public Source Source { get;set;}
}
You can do the same for your other class as well
I know it's too late, but this is a full code that can help you, give it a try if you like.
class Column
{
string plainText;
Regex reg = new Regex(#"(Source\b\w+\b\w+\b)(Destination\b\w+\b\w+\b)");
public Source Source {
get {
Match m = reg.Match(plainText);
Group source = m.Groups[0];
string[] s = source.Value.Split(new string[]{" "}, StringSplitOptions.RemoveEmptyEntries);
return m.Success ? new Source(new string[]{s[1],s[2]}) : null;
}
set {
Match m = reg.Match(plainText);
Group dest = m.Groups[1];
if(m.Success) plainText = value + " " + dest.Value;
}
}
public Destination Destination {
get {
Match m = reg.Match(plainText);
Group dest = m.Groups[1];
string[] s = dest.Value.Split(new string[]{" "}, StringSplitOptions.RemoveEmptyEntries);
return m.Success ? new Destination(new string[]{s[1], s[2]}) : null;
}
set {
Match m = reg.Match(plainText);
Group source = m.Groups[0];
if(m.Success) plainText = source.Value + " " + value;
}
}
//This is used to change the plainText
//for example: SetPlainText("Source home(1) type[3] Destination NewYork(3) Seattle[2]");
public void SetPlainText(string txt){
plainText = txt;
}
}
public class Source
{
public Source(string[] s){
Name = s[0];
Type = s[1];
}
public string Name { get; set; }
public string Type { get; set; }
public override string ToString(){
return string.Format("Source {0} {1}",Name,Type);
}
}
public class Destination
{
public Destination(string[] s){
Name = s[0];
Type = s[1];
}
public string Name { get; set; }
public string Type { get; set; }
public override string ToString(){
return string.Format("Destination {0} {1}",Name,Type);
}
}

Categories