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
Related
I have two objects with the same properties like this:
ObservableCollection<A> FooA
ObservableCollection<B> FooB
both model A and B have a property in common. I've created this method for update the property without create redundancy code:
public static void UpdateItemInCollection(A person, ObservableCollection<A> collection)
{
foreach (var m in collection)
{
m.Name = m.id == person.id;
}
}
But I can only pass as parameter FooA. How can I pass also FooB?
You have to use an interface or a parent (most likely abstract) class, if that property actually represents the same kind of data in both classes.
public interface INamed
{
string Name { get; }
}
public Person : INamed
{
public string Name {get; set;}
// etc.
}
public People : INamed
{
public string Name {get; set;}
// etc.
}
public static void UpdateItemInCollection(INamed person, ObservableCollection<INamed> collection)
{
foreach (var m in collection)
{
m.Name = m.id == person.id;
}
}
You can create an interface for both classes:
public interface AandB
{
string Name { get; set; }
}
Then implement it in the classes:
public interface AandB
{
string Name { get; set; }
}
public class A : AandB
{
public string Name { get; set; }
public string id { get; set; }
}
class B : AandB
{
public string Name { get; set; }
public string id { get; set; }
}
Modify your method to get the interface instead of the class:
public static void UpdateItemInCollection(AandB person, ObservableCollection<AandB> collection)
{
foreach (var m in collection)
{
m.Name = "whatever";
}
}
The collections must be the interface type:
ObservableCollection<AandB> FooA;
ObservableCollection<AandB> FooB;
And finally,you can call the method with both classes:
FooA = new ObservableCollection<AandB>();
A objA = new A();
objA.id = "1";
objA.Name = "test";
FooA.Add(objA);
FooB = new ObservableCollection<AandB>();
B objB = new B();
objB.id = "1";
objB.Name = "test";
FooB.Add(objB);
UpdateItemInCollection(objA, FooA);
UpdateItemInCollection(objB, FooB);
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 have two classes with some similar fields, some different, and a form that utilizes two different objects depending on what mode it's in (insert/edit).
Instead of using two different objects and if statements checking the form mode, I'd like to have one struct to be hydrated with either of the two objects fields so I can manipulate one object through the page life-cycle. Then separated the struct back to its respective object for insert/updating the DB.
Example of classes:
public partial class SomeClass
{
public Int32 B {get;set;}
public String C {get;set;}
public Boolean D {get;set;}
}
public class SomeOtherClass
{
public Int32 A {get;set;}
public Int32 B {get;set;}
public String C {get;set;}
}
Update with Solution Example:
public interface IInsertable
{
string SharedName { get; set; }
string SharedID { get; set; }
string editedFieldValue { get; set; }
long GetSuperSecreteInfo();
}
internal class InsertableImplementation : IInsertable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return -1;
}
}
public interface IUpdateable
{
string SharedName { get; set; }
string SharedID { get; set; }
string updatedFieldValue { get; set; }
Guid GenerateStevesMagicGuid();
}
internal class UpdateableImplementation : IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
public static class WonderTwinFactory
{
public static WonderTwins GenerateWonderTwin(IUpdateable updateable, IInsertable insertable)
{
var wt = new WonderTwins();
// who will win?
wt.SharedID = updateable.SharedID;
wt.SharedID = insertable.SharedID;
// you decide?
wt.SharedName = updateable.SharedName;
wt.editedFieldValue = "stuff";
return wt;
}
}
public class WonderTwins : IInsertable, IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return 1;
}
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
class Program
{
static void Main(string[] args)
{
IUpdateable updateable = new UpdateableImplementation();
IInsertable insertable = new InsertableImplementation();
WonderTwins dualImplementatin = WonderTwinFactory.GenerateWonderTwin(updateable, insertable);
IUpdateable newUpdateable = dualImplementatin as IUpdateable;
IInsertable newInsertable = dualImplementatin as IInsertable;
}
}
Have both classes implement an interface that defines the operations common to each, including both the fields that are shared (assuming the view needs to access them) and also a method to actually perform the operation that they represent (insert/edit).
Other way of doing such things is using C# dynamic object and assign properties directly. It may help to avoid any new type or interface and directly utilizing new dynamic object any time, as much as required.
var newObject = new {
objectOfClass1 = x.prop1,
objectOfClass2 = x.prop2
}
I have two complex objects that have exactly the same properties.
Now with AutoMapper, I usually will need to do something like this:
Mapper.CreateMap<ObjA, ObjB>();
But if one of the objects has a complex inner object, Ill need to map it too:
Mapper.CreateMap<ObjAInner, ObjBInner>();
Now I have a large object that expands all the time.
I don't want to maintain the CreateMap calls each time I add a complex inner object to the main object.
Now I can probably solve this with a recursive reflection on the main object and map all the types but I'd prefer not to do that.
Is there anyway I can tell AutoMapper to Create a full recursive map(also for inner types) on a complex object?
Something like this:
Mapper.CreateFullMapOnIdenticalObjectsWithInnerTypes<ObjA, ObjB>();
Edit:
Here's an example:
two identical classes with a different namespace:
namespace NameSpace1
{
public class Obj1
{
public string Str { get; set; }
public int Num { get; set; }
public InnerObj1 InnerObj1 { get; set; }
}
public class InnerObj1
{
public string StrInner1 { get; set; }
public int NumInner1 { get; set; }
public AnotherInnerObj1 AnotherInnerObj1 { get; set; }
}
public class AnotherInnerObj1
{
public string Str { get; set; }
}
}
namespace NameSpace2
{
public class Obj1
{
public string Str { get; set; }
public int Num { get; set; }
public InnerObj1 InnerObj1 { get; set; }
}
public class InnerObj1
{
public string StrInner1 { get; set; }
public int NumInner1 { get; set; }
public AnotherInnerObj1 AnotherInnerObj1 { get; set; }
}
public class AnotherInnerObj1
{
public string Str { get; set; }
}
}
Create a mock NameSpace1.Obj1:
public static NameSpace1.Obj1 Create()
{
return new NameSpace1.Obj1
{
Num = 10,
Str = "Obj1",
InnerObj1 = new NameSpace1.InnerObj1
{
NumInner1 = 11,
StrInner1 = "InnerObj1",
AnotherInnerObj1 = new NameSpace1.AnotherInnerObj1
{
Str = "AnotherInnerObj1"
}
}
};
}
This is what I would like:
Mapper.CreateMap<NameSpace1.Obj1, NameSpace2.Obj1>();
var obj1 = Create();
var obj2 = Mapper.Map<NameSpace2.Obj1>(obj1);
But this will throw an exception since I need to define inner mappings. This will work:
Mapper.CreateMap<NameSpace1.Obj1, NameSpace2.Obj1>();
Mapper.CreateMap<NameSpace1.InnerObj1, NameSpace2.InnerObj1>();
Mapper.CreateMap<NameSpace1.AnotherInnerObj1, NameSpace2.AnotherInnerObj1>();
var obj1 = Create();
var obj2 = Mapper.Map<NameSpace2.Obj1>(obj1);