So I have this code:
public class myClass
{
public string A { get; set; }
public string B{ get; set; }
//and so on
}
I want to add a constructor that takes a string input and have that constructor split the string on ','then use the split values to populate the class variables
What I Have Tried
I have tried to make a string with my variables values like so:
public void myVoid()
{
string s = "A,B,..etc";
string[] values = s.Split(',');
foreach (string item in values)
{
Console.WriteLine(item);
Console.ReadKey();
}
}
This returns my values one by one on each key press but this is just me getting my head around it.
So to clarify: I want to add a constructor that takes a string input and have that constructor split the string on ','then use the split values to populate the class variables
Is this what you want?
public class myClass
{
public myClass(string input)
{
var ar = input.Split(',');
if (ar.Length >= 2)
{
A = ar[0];
B = ar[1];
}
}
public string A { get; set; }
public string B{ get; set; }
//and so on
}
Use:
var myclass = new myClass("some,thing");
A simple approach would be:
public class myClass
{
public string A { get; set; }
public string B{ get; set; }
public myClass()
{
//default constructor
}
public myClass(string S)
{
string[] values = S.Split(',');
if (values.Length>=2)
{
this.A=values[0];
this.B=values[1];
}
}
}
However your goal is a bit fuzzy. E.g which value of splited string would appended on A and which in B?
Do you want this -
public class myClass
{
private string _a, _b;
public myClass(string args)
{
_a = args.Split(',')[0];
_b = args.Split(',')[1];
}
public string A { get { return _a; } set { _a = value; } }
public string B { get { return _b; } set { _b = value; } }
//and so on
}
public string A { get; set; }
public string B { get; set; }
public Sample(string strSplit) {
var values = strSplit.Split(',');
A = values[0];
B = values[1];
}
Sample dd = new Sample("James,Jonathan");
better use reflection
Related
I wonder if there's any way to match the names in a list with the elements in a class:
I have a class:
public class exampleClass
{
public string name { get; set; }
public string value { get; set; }
}
and a List: List<exampleClass> EnfSist
So that's the way the list is made. Now I would like to know how to match or identify the string inside "name" from my list. To match this class:
tbl_sistematicas b = new tbl_sistematicas
{
ap_enf_id_enfermedad = Convert.ToInt32(EnfSist[0].value),
ap_pac_inicio = Convert.ToInt32(EnfSist[1].value),
ap_pac_inicio_periodo = Convert.ToInt32(2].value),
ap_pac_duracion = Convert.ToInt32(EnfSist[3].value),
ap_pac_duracion_periodo = Convert.ToInt32(EnfSist[4].value),
ap_pac_tratamiento = EnfSist[5].value
};
Once being able to match the same names I won't have to specify each index of every element in the list. The elements in the list have the same name as in the table. Not all elements of the class are being used.
I have something like this: tbl_sistematicas bh = EnfSist.FindAll(x => x.name == bh.?????? );
If I understand the question, you can do this using something like automapper or ValueInjector
An example using ValueInjector
void Main()
{
List<exampleClass> EnfSist = new List<exampleClass>();
EnfSist.Add(new exampleClass { name = "ap_enf_id_enfermedad", value = "12" });
EnfSist.Add(new exampleClass { name = "apap_pac_inicio" , value = "34" });
// etc
tbl_sistematicas b = new tbl_sistematicas();
b.InjectFrom<MyInjection>(EnfSist);
}
public class MyInjection : KnownSourceValueInjection<List<exampleClass>>
{
protected override void Inject(List<exampleClass> source, object target)
{
foreach(var entry in source)
{
var property = target.GetProps().GetByName(entry.name, true);
if (property != null)
property.SetValue(target, Convert.ChangeType(entry.value, property.PropertyType));
}
}
}
public class exampleClass
{
public string name { get; set; }
public string value { get; set; }
}
public class tbl_sistematicas
{
public int ap_enf_id_enfermedad { get; set; }
public int apap_pac_inicio { get; set; }
public int ap_pac_inicio_periodo { get; set; }
public int ap_pac_duracion { get; set; }
public int ap_pac_duracion_periodo { get; set; }
public string ap_pac_tratamiento { get; set; }
}
Note, this will throw an exception if the value can not be converted to an int
I have 3/4 different models that each contain their own nested model. I need a way of iterating all fields, including those of the nested model and do a string replace (although not all fields are strings).
My initial idea was to write a method which allows for a 'dynamic' type to be passed.
Input model:
Name = Joe
Surname = Smith
Address = new ClientAddress
{
Line1: Item A
Line2: mistake
Line3: mistake
}
My example method:
MyMethod (dynamic passInModel)
{
....
passInModel.Replace("mistake","correction");
return passInModel;
}
Output:
Name = Joe
Surname = Smith
Address = new ClientAddress
{
Line1: Item A
Line2: correction
Line3: correction
}
Despite trying various ways of doing it I've not had any success in writing something that does the job.
You could write a method that accepts an object and use reflection to iterate through all the fields, but you're getting into messy territory there. In my opinion, even using dynamic here is messy.
Consider using a modified visitor pattern here. If your domain objects look like this:
public class ModelBase
{
}
public class MyModel1 : ModelBase
{
public string Name { get; set; }
public string Surname { get; set; }
public ClientAddress Address { get; set; }
}
public class MyModel2 : ModelBase
{
public string CompanyName { get; set; }
public string Region { get; set; }
public CompanyAddress Address { get; set; }
}
public class ClientAddress
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
}
public class CompanyAddress
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public List<string> AdditionalLines { get; set; }
}
Write a visitor that takes an abstract ModelBase and dispatches the correct type-safe visitor:
public class ModelFixVisitor
{
public ModelBase Visit(ModelBase model)
{
var asModel1 = model as MyModel1;
if (asModel1 != null)
{
return new Model1FixVisitor().Visit(asModel1);
}
var asModel2 = model as MyModel2;
if (asModel2 != null)
{
return new Model2FixVisitor().Visit(asModel2);
}
throw new NotImplementedException("Unknown model type.");
}
}
Then write a simple class for each type (and subtype) you need to visit:
public class Model1FixVisitor
{
public MyModel1 Visit(MyModel1 model)
{
model.Name = new StringFixVisitor().Visit(model.Name);
model.Surname = new StringFixVisitor().Visit(model.Surname);
model.Address = new ClientAddressFixVisitor().Visit(model.Address);
return model;
}
}
public class Model2FixVisitor
{
public MyModel2 Visit(MyModel2 model)
{
model.CompanyName = new StringFixVisitor().Visit(model.CompanyName);
model.Region = new StringFixVisitor().Visit(model.Region);
model.Address = new CompanyAddressFixVisitor().Visit(model.Address);
return model;
}
}
public class ClientAddressFixVisitor
{
public ClientAddress Visit(ClientAddress address)
{
address.Line1 = new StringFixVisitor().Visit(address.Line1);
address.Line2 = new StringFixVisitor().Visit(address.Line2);
address.Line3 = new StringFixVisitor().Visit(address.Line3);
return address;
}
}
public class CompanyAddressFixVisitor
{
public CompanyAddress Visit(CompanyAddress address)
{
address.Line1 = new StringFixVisitor().Visit(address.Line1);
address.Line2 = new StringFixVisitor().Visit(address.Line2);
address.AdditionalLines = new StringListFixVisitor().Visit(address.AdditionalLines);
return address;
}
}
public class StringFixVisitor
{
public string Visit(string element)
{
return element.Replace("mistake", "correction");
}
}
public class StringListFixVisitor
{
public List<string> Visit(List<string> elements)
{
return elements
.Select(x => new StringFixVisitor().Visit(x))
.ToList();
}
}
I'm sure the code could be refactored and optimized, but it should express the general idea.
What I like about this type of solution is that it breaks the problem down into small, manageable chunks: How do I fix a string? How do I fix a ClientAddress?
Fixing entire models then becomes simple composition of these smaller classes. It's a little more verbose, but you get to keep type safety, and don't have to mess with reflection.
You can use the power of .Net reflection to solve this.
I created a class called DeepStringReplacer. Using reflection it iterates through object properties and if the type is string, perform string replace.
Check the code below:
public class DeepStringReplacer
{
public object Replace(object input, string oldValue, string newValue)
{
if (input is string)
{
return input.ToString().Replace(oldValue, newValue);
}
var fields = input.GetType().GetProperties();
foreach (var field in fields)
{
var fieldValue = field.GetValue(input);
field.SetValue(input, Replace(fieldValue, oldValue, newValue));
}
return input;
}
}
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public ClientAddress Address { get; set; }
}
public class ClientAddress
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
}
I build a rest service which output are json. I using Newtonsoft.Json.
This is my class.
public class DownloadPDA
{
public List<FRUTE> lsRute { get; set; }
public List<FCUSTMST> lsCustomer { get; set; }
public List<FMASTER> lsMaster { get; set; }
public List<FNOTEC> lsNotec { get; set; }
public List<FINFO> lsInfo { get; set; }
public List<FBRAND> lsBrand { get; set; }
public List<FKPL> lsKpl { get; set; }
}
but when I test my rest service my result are:
{"downloadDataResult":"{"lsBrand":[{}],"lsCustomer":[{},{},{}],"lsInfo":[],"lsKpl":null,"lsMaster":[{},{},{},{},{}],"lsNotec":[],"lsRute":[{},{},{}]}"}
it not show the data in list. I know something is wrong. Can anybody help?
This one of my collection class
public class FRUTE
{
private String norute;
private String custno;
private String flag;
private String st_visit;
private float amount;
private int jmlvisit;
public FRUTE() { }
public void getData(DCTRTDTO dto) {
this.norute = dto.NOROUT;
this.custno = dto.NOCUST;
this.flag = dto.FLAG;
this.st_visit = "not yet";
this.amount = 10;
this.jmlvisit = 1;
}
public static List<FRUTE> getList(List<DCTRTDTO> lsRute)
{
List<FRUTE> ls = new List<FRUTE>();
FRUTE info = new FRUTE();
foreach (DCTRTDTO dto in lsRute)
{
info.getData(dto);
ls.Add(info);
}
return ls;
}
}
Your FRUTE class doesn't have public properties that are required for Json serialization.
Encapsulate you private fields and all will work as expected.
public class FRUTE
{
private String norute;
private String custno;
public string Norute
{
get { return norute; }
set { norute = value; }
}
public string Custno
{
get { return custno; }
set { custno = value; }
}
//...
}
I have an array of data that can have 1 to 10 values in it. Based on the number of values in the array I want to select 1 of 10 differnt classes and place the values of the array in the class object.
This is what I have so far,
Array[] ar;
ar = PopulateTheArray();
int cnt = ar.Count();
Object ob = Activator.CreateInstance(null, "MyObject" + cnt);
There are 10 MyObject classes like this,
public class MyObject1
{
public string Column1 { get; set; }
}
public class MyObject2
{
public string Column1 { get; set; }
public string Column2 { get; set; }
}
public class MyObject3
{
public string Column1 { get; set; }
public string Column2 { get; set; }
public string Column3 { get; set; }
}
and so on.....
How do I loop threw the array to populate the object, since the object is created dynamically?
This class architecture really does look very strange. It appears that you have a convention that class MyObjectX will have exactly X properties named Column1 - ColumnX. I've never seen that before, nor can I think of any scenario where that would be appropriate.
In any case, I would strongly suggest you describe your problem domain and your current architecture so that others might be able to evaluate its appropriateness and perhaps suggest alternatives. For example, it's possible that just need to write one class that encapsulates an array (or maybe some other collection):
public class MyObject
{
public string[] Columns { get; private set;}
public MyObject(int numColumns)
{
Columns = new string[numColumns];
}
}
But I will try to answer the question as asked.
You can do something like this:
object ob = ...
object[] ar = ...
for (int i = 0; i < ar.Length; i++)
{
ob.GetType().GetProperty("Column" + i).SetValue(ob, ar[i], null);
}
What if you had an abstract base class?
public abstract class MyObjectBase
{
public abstract void Initialize(params object[] args);
}
Then your example becomes:
public class MyObject1 : MyObjectBase
{
public string Column1 { get; set; }
public override void Initialize(params object[] args)
{
this.Column1 = args[0];
}
}
public class MyObject2 : MyObjectBase
{
public string Column1 { get; set; }
public string Column2 { get; set; }
public override void Initialize(params object[] args)
{
this.Column1 = args[0];
this.Column2 = args[1];
}
}
public class MyObject3 : MyObjectBase
{
public string Column1 { get; set; }
public string Column2 { get; set; }
public string Column3 { get; set; }
public override void Initialize(params object[] args)
{
this.Column1 = args[0];
this.Column2 = args[1];
this.Column3 = args[2];
}
}
and so on.....
Called like so:
Array[] ar;
int cnt = ar.Count();
MyObjectBase ob = Activator.CreateInstance(null, "MyObject" + cnt);
ob.Initialize(ar);
Try this...
public interface IMyObject
{
}
public class MyObject1 : IMyObject
{
public string Column1 { get; set; }
}
public class MyObject2 : IMyObject
{
public string Column1 { get; set; }
public string Column2 { get; set; }
}
public class MyObject3 : IMyObject
{
public string Column1 { get; set; }
public string Column2 { get; set; }
public string Column3 { get; set; }
}
Interface IMyObject identifies your classes. Now create dynamically with Reflection...
var assemblyTypes = System.Reflection.Assembly.GetExecutingAssembly().GetTypes();
var instanceList = new List<IMyObject>();
foreach (Type currentType in assemblyTypes)
{
if (currentType.GetInterface("IMyObject") == null)
continue;
Console.WriteLine("Found type: {0}", currentType);
// create instance and add to list
instanceList.Add(Activator.CreateInstance(currentType) as IMyObject);
}
Hope this will help
Usually i just use a dictionay for key value pairs but I am expectig three columns.
then I need to compare the search term to see if it matches any value in the second column.
You could just return a DataTable if you wanted to do it quick and dirty. Otherwise, if the data represents something, you could create your own class to hold the three values in three properties on the object.
public class MyDataObject
{
public string Value1 { get; set; }
public string Value2 { get; set; }
public string Value3 { get; set; }
public bool MatchesSearchTerm(string term)
{
return Value2.Equals(term, StringComparer.OrdinalIgnoreCase);
}
}
class YourDatum
{
int Id { get; set; }
string Value1 { get; set; }
string Value2 { get; set; }
public bool Match(string term)
{
return Value2.ToUpperInvariant() == term.ToUpperInvariant();
}
}
var cachedResults = new Dictionary<int, YourDatum>();
//your database calls go here
foreach (var dbRow in dbRows)
{
cachedResults.Add(
idFromDb,
new YourDatum {Id=idFromDb, Value1=valueFromDb1, Value2=valueFromDb2});
}
//find a match in the results later on...
string searchTerm = "abcdef";
List<YourDatum> matches=
(from datum in cachedResults where
datum.Match(searchTerm) select datum).ToList();
What is "the search term"? Why do you need to store rows in the first place?
Assuming you have a good reason to store results locally and you only care about "any value in the second column", you may want to explore storing a List<dataTypeOfSecondColumn>.
public class QueryCache
{
public class DataObject
{
public bool Data1 { get; set; }
public string Data2 { get; set; }
public int Data3 { get; set; }
}
Dictionary<string, DataObject> _cache = new Dictionary<string, DataObject>();
public void AddToCache(DataObject obj_)
{
_cache.Add(obj_.Data2, obj_);
}
public bool ExistsInCache(string searchTerm_)
{
return _cache.ContainsKey(searchTerm_);
}
public DataObject this[string searchTerm_]
{
get
{
return _cache[searchTerm_];
}
}
}