how to add constructors parameter to a list? - c#

I got a list of classes called classList. Each class in this list has a constructor with a string parameter that contains some info about the class. I want to iterate through the classList and then add all the constructor parameters to a stringarray.
How can I do this?
public Main()
{
classList = new List<class>();
class1 = new class1("class1 information");
class2 = new class2("class2 information");
classList.Add(class1);
classList.Add(class2);
}
public void getConstructorParametersToList()
{
string[] myArrayList = null;
for(int i = 0; i < classList.Count; i++)
{
//Add the parameters from the constructors to a string array
myArrayList[i] = parameterfromconstructor
}
}
public void doSomething()
{
foreach (string s in myArrayList)
{
Console.WriteLine(s);
}
}
//Output:
//Class1 information
//Class2 information

You can store that constructor parameter in class field or property and later access it.
public interface IParameterizedClass
{
string ClassParameter {get}
}
public class class1 : IParameterizedClass
{
public string ClassParameter {get; private set;}
public class1(string someParameter)
{
// do some work
ClassParameter = someParameter;
}
}
public class class2 : IParameterizedClass
{
public string ClassParameter {get; private set;}
public class2(string someParameter)
{
// do some work
ClassParameter = someParameter;
}
}
public void getConstructorParametersToList()
{
string[] myArrayList = null;
for(int i = 0; i < classList.Count; i++)
{
//Add the parameters from the constructors to a string array
myArrayList[i] = (classList[i] as IParameterizedClass).ClassParameter;
}
}

Related

How to creat a method to sort a 1D array of different customers type?

public void sortByType(){}
what should i enter here if i have three types of customers different in the way they pay
I have a class customer that inhereted 3 other classes they have a name ,id ,balance and a name of the books array and the date of barrowing and returning how can i sort them by
types??
class Book
{
public string BName { get;set; }
public string Day { get;set; }
public string Month { get;set;} }
public string Year { get;set;} }
public override string ToString(){}
}
then I created an abstract class Customer
abstract class Customer
{
protected string name;
protected double balance;
protected double ID_num;
protected Book[] rental_books = new Book[3];
public string Name { get { return name; } set { name = value; } }
public double Balance { get { return balance; } set { balance = value; } }
public double ID_NUM { get { return ID_num; } set { ID_num = value; } }
public override string ToString() {}
public abstract void BarrowBook(string bn, string d, string m, string y);
public abstract void ReturnBook(string bn, string d, string m, string y);
public abstract void AddToBalance(double sum);
}
and inherted it to the other three child classes and add what I need to each method
class NormalCustomer : Customer{}
class MemberCustomer : Customer{}
class StudentCustomer : Customer{}
then I created a library class
class Library
{
private Customer[] customers;
private int MaxCust=0;
private int count = 0;
public Library(int MaxCust) { this.MaxCust = MaxCust; }
public void Add(Customer c) { customers[count++] = c; }
public void ToString() {
public void SortByBalance()
{
double hold;
for (int i = 0; i < customers.Length - 1; i++)
for (int k = 0; k < (customers.Length - 1) - i; k++)
{
if (customers[k].Balance > customers[k + 1].Balance)
{
hold = customers[k].Balance;
customers[k].Balance = customers[k + 1].Balance;
customers[k + 1].Balance = hold;
}
}
}
}
so all i need now is the methode i mentioned above and how to creat it
let's take your classes
public class Customer { ... }
public class NormalCustomer : Customer{}
public class MemberCustomer : Customer{}
public class StudentCustomer : Customer{}
Providing an array which contains all the children in a mixed order:
Customer [] array = new Customer[]
{
new StudentCustomer(),
new MemberCustomer(),
new NormalCustomer(),
new MemberCustomer(),
new StudentCustomer(),
new StudentCustomer(),
new NormalCustomer(),
};
You can use the method: OfType to extract the individual types:
var children_1 = array.OfType<NormalCustomer>();
var children_2 = array.OfType<MemberCustomer>();
var children_3 = array.OfType<StudentCustomer>();
Now you simply need to concatenate them into a single collection using the Concat method. It expects that the second collection contains the same type of elements so you need to cast it temporarily to the parent type:
Customer [] sorted children_1.Cast<Customer>().Concat(children_2).Concat(children_3).ToArray();

Cast generic collection item type

The following code illustrates a situation I'm having. The real code use different names and get values in other ways, but they match with what I need an answer. Specifically in lines 76-89 (the only lines I control) I need to extract a variable of type "ICollection" with the values and I don't like none of the used approaches. Is there another approach to do it without to create class "AbstractCollection"?
namespace ConsoleApp1
{
using System.Collections.Generic;
using System.Linq;
interface IEntity
{
string Id { get; }
string Name { get; }
}
class Entity : IEntity
{
public Entity(string id, string name)
{
Id = id;
Name = name;
}
public string Id { get; }
public string Name { get; }
}
interface ICollection<TGeneric>
{
IEnumerable<TGeneric> Items { get; }
}
class Collection<TGeneric> : ICollection<TGeneric> where TGeneric : Entity, IEntity
{
public IEnumerable<TGeneric> Items { get; set; }
}
class AbstractCollection<TConcrete, TAbstract> : ICollection<TAbstract> where TAbstract : class, IEntity
{
public AbstractCollection(ICollection<TConcrete> collection)
{
this._Items = new List<TAbstract>();
if (collection?.Items != null)
{
foreach (TConcrete concreteItem in collection.Items)
{
TAbstract abstractItem = concreteItem as TAbstract;
this._Items.Add(abstractItem);
}
}
}
public IEnumerable<TAbstract> Items
{
get { return this._Items; }
set { this._Items = value?.ToList(); }
}
private IList<TAbstract> _Items { get; set; }
}
class EntityCollection : Collection<Entity>
{
public EntityCollection()
{
var items = new List<Entity>()
{
new Entity("1", "Name1"),
new Entity("2", "Name2"),
new Entity("3", "Name3")
};
Items = items;
}
}
class Context
{
public Context()
{
var concreteItems = new EntityCollection();
// I can modify from this line to the end of the method but not any code before.
// I expected values in "list1" but is null.
var list1 = concreteItems as ICollection<IEntity>;
var list2 = concreteItems as ICollection<Entity>;
var abstractItems = new List<IEntity>();
foreach (Entity concreteItem in concreteItems.Items)
{
IEntity abstractItem = concreteItem as IEntity;
abstractItems.Add(abstractItem);
}
// Why "list3" is null?
var list3 = abstractItems as ICollection<IEntity>;
// I want to avoid class "AbstractCollection"
var list4 = new AbstractCollection<Entity, IEntity>(list2);
// Finally "list5" has value in the way I want it.
var list5 = list4 as ICollection<IEntity>;
}
}
class Program
{
static void Main(string[] args)
{
var context = new Context();
}
}
}
Covariance guides to the solution:
interface ICollection<out TGeneric>
{
IEnumerable<TGeneric> Items { get; }
}

Func list for storing function pointer and parameter value

I want to store a list of functions with their parameter value and later when I am done adding function to the list. I want to execute all in the order I have added.
For example, I want to use func instead of action and don't want to create anonymous functions while calling parametered function:
Dynamic function list class to hold a function list and execute it later.
class DynamicFunctionList
{
public List<Action> DynamicList = new List<Action>();
public void Execute()
{
foreach (var obj in DynamicList)
{
obj();
}
}
}
some class with functions
public class SomeClass
{
public void PrintHello()
{
Console.Write("Hello");
}
public void PrintBye()
{
Console.Write("Print Bye");
}
public int GetPrinterValue()
{
return 2;
}
public int Add(int a, int b)
{
return (a + b);
}
}
And this is how you will use it
public static void MainClass()
{
var first = 0;
var second = 0;
var dfList = new DynamicFunctionList();
var sClass = new SomeClass();
dfList.DynamicList.Add(() => first = sClass.GetPrinterValue()); // problem line
dfList.DynamicList.Add(sClass.PrintBye);
dfList.DynamicList.Add(sClass.PrintHello);
dfList.DynamicList.Add(() => second = sClass.Add(2, 3)); // problem
dfList.Execute();
}
I do something like that:
public void main()
{
List<MethodInvoker> methods = new List<MethodInvoker>();
methods.Add(new MethodInvoker(SomeMethod));
foreach (var method in methods)
{
method.Invoke();
}
}
public void SomeMethod()
{
//... do something
}
EDIT 1:
You can use MethodBase.Invoke from System.Reflection namespace (more infos: https://msdn.microsoft.com/en-us/library/a89hcwhh%28v=vs.110%29.aspx)
You can do something like that:
public class DynamicMethod
{
public string ClassName { get; set; }
public string MethodName { get; set; }
public object[] Parameters { get; set; }
public static object InvokeMethod(DynamicMethod methodInfo)
{
var magicType = Type.GetType(methodInfo.ClassName);
var magicConstructor = magicType.GetConstructor(Type.EmptyTypes);
var magicInstance = magicConstructor.Invoke(new object[] {});
var magicMethod = magicType.GetMethod(methodInfo.MethodName);
return magicMethod.Invoke(magicInstance, methodInfo.Parameters);
}
}
public class Example
{
public static void main()
{
var d1 = new DynamicMethod
{
ClassName = "SomeClass",
MethodName = "Add",
Parameters = new object[] { 1, 2 }
};
var returnedValue = DynamicMethod.InvokeMethod(d1);
Console.WriteLine(returnedValue.ToString());
}
Also you can add more information to this class, like some way to store the returned type to do the properly cast.

How to trigger a Generic Class method recursively changing the type of T?

I've created a Generic Class to parse some data into another instance of a class (MyClass1). Since MyClass1 has only built-in C# types, my GenericMethod works fine. The problem starts to grow when MyClass1 has another MyClass2 property and I still want to invoke my GenericMethod to parse my data.
I can't trigger my Generic Class method inside its scope since I need to change the type of T. Is there any way to solve this problem?
public class MyClass1
{
public int MyIntProperty { get; set; }
public string MyStringProperty { get; set; }
public MyClass2 MyClass2Property { get; set; }
}
public class MyClass2
{
public int MyOtherIntProperty { get; set; }
public string MyOtherStringProperty { get; set; }
public bool MyOtherBoolProperty { get; set; }
}
public class MyGenericClass<T> where T : class
{
public static T MyGenericMethod()
{
T o = (T)Activator.CreateInstance(typeof(T));
PropertyInfo[] pi = typeof(T).GetProperties();
for(int i = 0; i < pi.Count(); i++)
{
if(pi[i].Name == "MyClass2Property")
{
//How to proceed ?
MyGenericClass<???>.MyGenericMethod();
}
else
{
pi[i].SetValue(o, Convert.ChangeType(someValue, pi[i].PropertyType), null);
}
}
}
}
public static void Main(string[] args)
{
MyClass1 mc1 = MyGenericClass<MyClass1>.MyGenericMethod();
//Do something with mc1
}
You can look at this post
and maybe try something like this
public static class MyGenericClass<T> where T : class
{
public static T MyGenericMethod()
{
T o = (T)Activator.CreateInstance(typeof(T));
PropertyInfo[] pi = typeof(T).GetProperties();
for(int i = 0; i < pi.Count(); i++)
{
if(pi[i].Name == "MyClass2Property")
{
//How to proceed ?
Type t = typeof (MyGenericClass<>);
Type genericType = t.MakeGenericType(new System.Type[] { pi[i].PropertyType });
var c = Activator.CreateInstance(genericType);
dynamic mgm = Convert.ChangeType(c, genericType);
mgm.MyGenericMethod();
}
else
{
pi[i].SetValue(o, Convert.ChangeType(someValue, pi[i].PropertyType), null);
}
}
}
Depending on your needs, you could also define some additional meta information about the property indicating what you would like to do with it if found.
Building on others' comments and answers, here is what I came up with including an attribute decoration that allows you to dynamically build objects and has the following enhancements:
Properties can be named anything you want
No need for if statements as new properties are added.
No need for the MyGenericMethod method to ever change.
Additional meta-information can be added to the custom attribute to add further customization in the future.
Objects can be nested as deeply as needed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Dynamic;
public class MyClass1 {
public int MyIntProperty { get; set; }
public string MyStringProperty { get; set; }
[MyCustom()]
public MyClass2 MyClass2Property { get; set; }
}
public class MyClass2 {
public int MyOtherIntProperty { get; set; }
public string MyOtherStringProperty { get { return "oooh, fancy"; } set {} }
public bool MyOtherBoolProperty { get; set; }
}
public static class MyGenericClass<T> where T : class {
public static T MyGenericMethod() {
T o = (T)Activator.CreateInstance(typeof(T));
PropertyInfo[] pi = typeof(T).GetProperties();
for (int i = 0; i < pi.Count(); i++) {
if (pi[i].GetCustomAttributes(true).Any() && pi[i].GetCustomAttributes(true).Where((x) => x is MyCustomAttribute).Any()) {
//How to proceed ?
var c = Activator.CreateInstance(pi[i].PropertyType);
Type t = typeof(MyGenericClass<>);
Type genericType = t.MakeGenericType(new System.Type[] { pi[i].PropertyType });
MethodInfo m = genericType.GetMethod(MethodInfo.GetCurrentMethod().Name);
c = m.Invoke(null, null);
pi[i].SetValue(o, c, null);
} else {
//Normal property assignment.
}
}
return o;
}
}
public class Program {
public static void Main(string[] args) {
MyClass1 mc1 = MyGenericClass<MyClass1>.MyGenericMethod();
//Do something with mc1
Console.WriteLine(mc1.MyClass2Property.MyOtherStringProperty);
Console.ReadLine();
}
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple=false)]
public class MyCustomAttribute : Attribute {
}
I tweaked this so it can be run as is.
Edit:
I also changed the code to invoke the method being called on itself to avoid a "magic string".

Instantiating a class given a generic abstract type

Using this model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
#region Abstracts definitions
abstract class AnAbstract
{
public string Name { get { return this.GetType().Name; } }
public bool IsNumeric { get { return this is ANumericAbstract; } }
public /*abstract*/ string Description = default(string);
}
abstract class ANumericAbstract : AnAbstract
{
public /*abstract*/ double Min = double.MinValue;
public /*abstract*/ double Max = double.MaxValue;
}
abstract class ANonNumericAbstract : AnAbstract
{
public List<Object> objects = new List<Object>();
}
#endregion Abstracts definitions
#region Concrete definitions
class NumericImpl : ANumericAbstract
{
new public const string Description = "A numeric implementation";
new public const double Min = 0;
new public const double Max = 1000;
public NumericImpl()
{
}
}
abstract class AnotherImpl : ANonNumericAbstract
{
public AnotherImpl()
{
objects.Add("one");
objects.Add("two");
objects.Add("three");
}
}
class SideA : AnotherImpl
{
new public const string Description = "Disc side A";
}
class SideB : AnotherImpl
{
new public const string Description = "Disc side B";
}
#endregion Concrete definitions
partial class Parameter
{
public string Name { get; set; }
public string Description { get; set; }
public bool IsNumeric { get; private set; }
public double Min { get; private set; }
public double Max { get; private set; }
public List<Object> Values { get; private set; }
private Parameter()
{
Values = new List<Object>();
}
}
}
With this, I pretend to define a hierarchy of classes for which I can have some abstract properties (Name,Description,IsNumeric) and at the end of the hierarchy there should be some classes which mandatorily define those properties; in the case of ANumericAbstract they should have additional specific properties, e.g. Min and Max.
Now here's the problem.
I'm attemtping to be able to create instances of Parameter which take a generic AnAbstract and read from it some values to fill in the Parameter properties, à la
Parameter<ANumericAbstract> ParamNum = new Parameter<NumericImpl>();
where a Parameter constructor would take in the passed type and "fill in the blanks". In other words, I'm trying something like:
using System;
namespace ConsoleApplication1 {
partial class Parameter
{
public static Parameter NewParameter<T>() where T : AnAbstract
{
Parameter Parameter = new Parameter();
// THESE DON'T WORK:
this.Name = T.Name;
this.Description = T.Description;
this.IsNumeric = T.IsNumeric;
if (this.IsNumeric)
{
this.Min = (T as ANumericAbstract).Min;
this.Max = (T as ANumericAbstract).Max;
}
else
{
foreach(Object val in (T as ANonNumericAbstract).Values)
{
this.Values.Add(val);
}
}
return Parameter;
}
}
class Program
{
private AnAbstract Number = new NumericImpl();
static void Main(string[] args)
{
}
// THESE DON'T WORK:
private static Parameter<ANumericAbstract> ParameterNum =
Parameter.NewParameter<NumericImpl>();
private static Parameter<ANonNumericAbstract> ParameterA =
Parameter.NewParameter<SideA>();
private static Parameter<ANonNumericAbstract> ParameterB =
Parameter.NewParameter<SideB>();
}
}
Obviously the syntax is invalid, but I'm not sure if I'm going in the right direction. Is there some Generics syntax that I'm not using properly? Should I just be done with it and use Getters and Setters à la Java? :-) At this point, just doing the
Parameter par = new Parameter { Name = NumericImpl.Name, /* ... */ };
might seem more sensible...
Firstly you should not use New keyword on your properties.
Consider virtual keyword:
abstract class AnAbstract
{
public virtual string Name { get { return this.GetType().Name; } }
public virtual string Description { get { return String.Empty; } }
}
abstract class ANumericAbstract : AnAbstract
{
public virtual double Min = double.MinValue;
}
class NumericImpl : ANumericAbstract
{
public override string Description { get { return "A numeric implementation"; } }
public override double Min { get { return 0; } }
}
1) You can place an instance of you type in Parameter constructor and have Parameter instance.
partial class Parameter
{
public Parameter(AnAbstract inputObject)
{
this.Name = inputObject.Name;
// etc
}
}
private static Parameter ParameterNum = new Parameter(new NumericImpl());
2) The second way is to use reflection to create an instance of object with initial parameters.
partial class Parameter<T> where T : AnAbstract
{
public static Parameter<T> NewParameter<T>() where T : AnAbstract
{
Parameter<T> parameter = new Parameter<T>();
AnAbstract instance = (AnAbstract)Activator.CreateInstance(typeof(T));
parameter.Name = instance.Name;
// etc
return parameter;
}
}
private static Parameter<NumericImpl> ParameterNum =
Parameter<NumericImpl>.NewParameter();
3) Make Parameter class static and create in via static constructor.
static partial class Parameter<T> where T : AnAbstract
{
public static string Name { get; set; }
//etc
}
static partial class Parameter<T> where T : AnAbstract
{
static Parameter ()
{
AnAbstract instance = (AnAbstract)Activator.CreateInstance(typeof(T));
Parameter<T>.Name = instance.Name;
//etc
}
}
In the last example you can use this class like this:
String someName = Parameter<NumericImpl>.Name;

Categories