Looping through class with multiple ObservableCollection<T> - c#

I have a class:
public class ClassA
{
string Field1;
int Field2;
ObservableCollection<ClassB> col1;
ObservableCollection<ClassC> col2;
ObservableCollection<ClassD> col3;
ObservableCollection<ClassE> col4;
ObservableCollection<ClassF> col5;
// ...
}
In my application, when the user hits save I need to loop through this class and perform actions with each of its members.
I can use reflection to go through the normal fields, but not sure how to:
get each of the collections
identify what type it holds
loop its items and cast each collection item to its Type so can work with it.
Background:
I have multiple datagrids on a wpf app, with the class structure above being the viewModel datacontext.
When user hits save I need to do save each item in the viewmodel to its own relevant table in the database via stored procs.
Once I have the a collection I need to test IF "is a class b" or IF "is a class C" and then use the particular method on it, with that method receiving the actual Type.
Would be much cleaner than hardcoding the class.

Reflection can be used to interrogate a type hierarchy at run-time, however this quickly becomes painful if you're trying to do so with generics, more so if you think you can access the type at runtime as you would at compile-time.
The code below demonstrates the principal behind (1) and (2) in your question. (3) is harder to answer without more detail on how you wish to use the generic types contained in each ObservableCollection.
var instance = new ClassA();
var fields = instance.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach(var field in fields)
{
Console.WriteLine("Field name: {0}. Type:{1} IsGeneric:{2}", field.Name, field.FieldType.Name, field.FieldType.IsGenericType);
if(field.FieldType.IsGenericType)
{
var genericArgs = field.FieldType.GenericTypeArguments;
foreach(var genericArg in genericArgs)
{
Console.WriteLine("\tGenericArg Type:{0}", genericArg.Name);
}
}
}
Live demo: http://rextester.com/AJVS85556

Related

C#.NET: Class or Collection with a maximal and defined set of fields, but with dynamic returns of fields

Okay, what do I need?
I'm looking for a class (object by schema instance), which has a maximal number of hard defined fields. And a dynamic way to "use" (create, read, update, delete) a "sub-object" of it.
Like this:
public class Books
{
public int Id;
public string Title;
public string Isbn;
public int Pages;
public int Price;
public string Author;
public string DescriptionSmall;
public string DescriptionLong;
public string Publisher;
//create constructor:
public Books(int id, string title, string isbn, ...) {
Id = id,
Title = title,
Isbn = isbn,
...
//only the setted fields should be usable
}
//add fields (only pre-defined should be possible)
public void|bool Add(Dictionary<string, object>) { //or List<> overload for only field names (without values)
//add fields
}
//get a return (only pre-defined should be possible)
public void|bool return Get(Dictionary<string, object>) {
//return as a sub-object
}
//delete void|bool fields
public Delete(Dictionary<string, object>) {
//delete fields
}
//update fields
public Update(...) {
...
}
}
//and than I can use it like a object, createtd by instance or what ever. :/
var smallBooks = new Books(id = 1, Title = "Lord of tha weed"); //can use all methods but for the moment only the created fields, but can add more fields by add()...
I dislike to have hunderds of models/entites for all possible field-combinations.
The problem is, that I try to update a database via GraphQL server.
Is there a way to return a part of the object, which is a "sub-" object, itself?
Yeah I know, I also can create a dynamic obejct with help by ExpandoObject or create a Collection/Dictionary to send.
It's important, that the not used fields are not only NULL, because some fields in my database are nullable and can work with NULL as a value.
-------------------------[Addition: 2021-07-27]-------------------------
Okay, I obviously expressed myself ambiguously. I have a table in the DB and the fields in it are firmly defined. When updating data, however, I only need a few fields from the complete list of all fields. The problem, I would like to keep the selection of the fields dynamic instead of having to create numerous entities or DTOs as part of the main model.
I'm looking for a simple way to create a dynamic sub-object in the code that contains the same methods, but only a (freely selectable) selection of the total fields.
Within my project it happens from time to time that data should be collected and processed before that data is finally sent to the server as a dynamic subset, e.g. as an update (GraphQL update mutation). An existing data set (main model) should, as it were, reflect the current status of the database. But only individual fields are required for an update.
I just want to avoid having to create countless classes for all combinations and choices.
Is there a way to derive a dynamic partial selection from the main class, which, for example, only contains 1 to x fields, but possibly has a reference to the main class and its fields (sync). - So an instance from the main class and dynamically derive further sub-objects from this object.
I used to simply create a dictionary<string, object> with field names and values ​​and use mainDict.GetKeys() or mainDict.Select(f => f.key / f.value) from this selection in a complex method to create a "small copy" to update only separate fields (via uploading to the server). - But I'd like to use oop with classes, instances and maybe dynamic objects (expando objects). - But I don't know how. ;) Sorry.
I'm open to any suggestion. If possible, simple and with little code, but as dynamic as possible.
To expand on my comment. A more complex would be like this:
In this example the Course has some fixed number of fields but expands on that using the CouresField (many-to-many) connection to connect several FormFields. The FieldValue entity holds the values for the fields in combination with the UserFieldValue (many-to-many) for each user (in this case).
Now maintaining all of this is a lot of work but you can use the EntityFramework to maintain the many-to-many connections for you. No need to do all the coding yourself. It will be automatically generated.

Unable to get separate references during iteration

I am attempting to iterate through the members of a list which implement a particular interface, called ImplementsGraphics and then call the method GetModels and add the return result to a list.
However, whenever I attempt to iterate through my objects, and perform the casting operation, I appear to be overwriting the same reference during my iteration. I have deduced that my problem is something to do with where, when and how I am instantiating my variables, but I can not decipher exactly what the intended behavior is.
I've tried numerous permutations of the following code:
public List<Model> GetModels()
{
var models = new List<Model>();
foreach (Actor actor in registeredActors.Where(n=>n is ImplementsGraphics))
{
var graphicActor = (ImplementsGraphics)actor;
models.AddRange(graphicActor.GetModels());
}
return models;
}
The problem line is var graphicActor = (ImplementsGraphics)actor; but I don't know how to write it such that declaring graphicsActor does not overwrite the existing instances of it stored in models.
Before my first several rounds of troubleshooting, I had
public List<Model> GetModels()
{
var models = new List<Model>();
foreach (Actor actor in registeredActors)
{
if((ImplementsGraphics)actor != null)
models.AddRange(((ImplementsGraphics)actor).GetModels());
}
return models;
}
Which I expected to work, as I had thought actor was safe across iteration, but apparently not.
Desired Behavior:
Return a list, which is all the return results of GetModels() for ever Actor in RegisteredActors which implements ImplementsGraphics
Actual Behavior:
Returns a list, which is the same return value repeated for each Actor in Registered Actor, which implements ImplementsGraphics.
EDIT:
In the class StaticActor which is a child of Actor and implements ImplementsGraphics its defined as follows:
public List<Model> GetModels()
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = this.Transform.WorldMatrix;
}
}
return new List<Model> { Model };
}
Additonally, I have tried two other approaches which also failed. A for loop, which itereated through all of RegisteredActors, and checked if they implemented ImplementsGraphics, explicitly calling them by their index within RegisteredActors
And a LINQ query, which went
var models = RegisteredActors.Where(n=>n is ImplementsGraphics).SelectMany(n=>((ImplementsGraphics)n).GetModels())
EDIT 2:
The deinfitions of my classes are largely irrelevant, if you want a reproducable example of the behaviour I'm having trouble with, here is a far simpler example.
class MyClass
{
MyOtherClass foo = new MyOtherClass();
int bar = 0;
MyOtherClass GetOtherClass()
{
foo.bar = bar;
return foo;
}
}
class MyOtherClass
{
int bar = 0;
}
List<MyClass> MyCollection = new List<MyClass> {new MyClass(bar = 1), new MyClass(bar = 2), new Myclass(bar = 3)};
List<MyOtherClass> MyOtherCollection = new List<MyOtherClass>();
foreach(MyClass member in MyCollection)
{
MyOtherCollection.Add(member.GetOtherClass());
}
If you were to execute the above code, I expect that the value of MyOtherCollection's bar properties would be: 1, 2, 3
However, the actual result is that:
During the first iteration the values are 1
During the second iteration the values are 2, 2
During the third iteration the values are 3, 3, 3
I would appear, since none of the provided code states, only implies, that you are attempting to reuse a reference to single Model instance to draw multiple objects. Then you are adding multiple references of the same instance to the List.
The solution may be as simple as removing the static modifier from all Model variables and/or container objects.
Normally, the solution would be to create a Deep Copy of the object when it is added to the List, however, it is not directly possible to do this in XNA *1. (not that you would want to)
It would be better to allow each Actor, or StaticActor, object to directly pass its own Model(s) through the GetModels() method in the interface implementation, instead of using the additional class MyOtherClass.
*1. XNA does not expose a public constructor for the Model class. It is possible to do this using reflection. In MonoGame, there is a public Constructor available.
I tend to split my derived Classes and subsequent Lists based on properties like "StaticCollidables","DrawableStaticCollidables" and "DrawableMovingCollidables"...
This technique may require more upfront coding(and therefore is not as "elegant"), but, it is more efficient in terms of memory overhead(8 bytes + (4(32 bit) or 8(64 bit) bytes depending on sizeof(Object)) per List) and CPU overhead(no casting or is).
If you are attempting to reuse the same model, but place it in different locations, use the DrawInstancedPrimitives method using the VertexBuffers contained within each Mesh of the model.
Please comment on which of the above solutions worked for you(if any). If I have missed something please let me know, so I can correct the answer.

C# Linq using variable for Model

Trying to write a piece of code that is dynamic in that it can accept any number of possible model definitions.
Current hard code is:
var items = _context.Events.ToList();
foreach (var item in items)
{
(...)
}
What I would like to do is to make the _context.Events.ToList(); be more like _context.{variable that holds model name}.ToList();
Something like:
var modelName = "Table1"
var items = _context.modelName.ToList();
foreach (var item in items)
{
(...)
}
I thought about declaring items as a generic variable, that way it was available to the entire method even if set inside an if or switch, but no idea on what to declare it as.
Is something like this possible?
Try this :
var table = (ITable)context.GetType()
.GetProperty(modelName)
.GetValue(context, null);
I hope be helpful :)
Entity Framework has a generic Set<TEntity> accessor, but the type must be known at compile-time:
var foo = _context.Set<Foo>();
If you have the type as a string variable, though, your options are extremely limited. You can technically use reflection to get at the right DbSet, but you're going to lose the generic IQueryable<TEntity> interface, and you'll be stuck with the much more limited IQueryable interface, and by "much more limited", I mean you basically can't do anything but materialize the set.
If you want to type it via a string variable, but still have at least some querying ability, you'll need to employ a base class that's shared between all the entity types you'd want to use in this way. For example, if you have different "event" types, and you can make them all inherit from Event, then you could do something like:
MethodInfo method = typeof(Queryable).GetMethod("OfType");
MethodInfo generic = method.MakeGenericMethod(new Type[] { eventType });
var set = (IQueryable<Event>)generic.Invoke(null, new object[] { _context.Events });
If your eventType was "Film", for example, that would effectively give you the same queryset as something like _context.Set<Film>() (where Film would be a derived class of Event). You could then utilize your normal LINQ query functionality like Where, Select, etc. on set.

Extracting the value from a Member Expression that contains a parameter

How do I extract a value from a Member Expression where the expression within the Member Expression is not a Constant, but a Parameter Expression.
I am building a small Linq to MDX ORM for our company.
In my generator template, each Dimension found in the database is a class, and in each dimension, there are the Attribute properties that are found for that dimension. After all the dimension classes are generated, a higher level Cube class is generated that contains the Dimensions as properties, as well as the Measures for that cube. After all the cube classes are generated, a final class is built that contains the cube classes that were generated as Cube<MyCube> properties, where the Cube<> is my IQueryable type. Here's an example.
//Generated cs file example:
public partial MyDatabase : CubeBase
{
//Some base implementation goes here
public Cube<FooCube> FooCube { get { return new Cube<FirstCube>(new Provider("connection string"); } }
//Any other cubes would follow here that were found on this database.
}
//A calendar dimension
public class FooCube_CalendarDimension
{
public Attribute WeekEnding { get { return new Attribute("[Calendar].[Week Ending]"); } }
public Attribute Month { get { return new Attribute("[Calendar].[Month]"); } }
public Attribute Year { get { return new Attribute("[Calendar].[Year]"); } }
}
//The "FooCube"
public partial class FooCube
{
//List Dimensions
public FooCube_Calendar_Dimension Calendar { get { return new FooCube_Calendar_Dimension(); } }
//Other dimensions here
[Measure]
public string RetailDollars { get { return "[Retail Dollars]"; } }
// Other measures here
}
Now, an example of a very basic linq query to query the cube:
//using MyDatabase = db
var mdx = from cube in db.FooCube
where cube.Calendar.Year == "2014"
select new
{
Month = cube.Calendar.Month.Children
Dollars = cube.RetailDollars
}
For example, I'm trying to get the value from cube.Calendar.Month.Children, which comes from the Attribute object that is a property of the FooCube_Calendar_Demsion class, that is in itself a property in the "FooCube" class.
I tried the answer from Access the value of a member expression, but I get the error, "the 'cube' parameter was not referenced" when it tries to compile the lambda expression. The value that it passes to the attribute class's constructor is stored in a property, and that's the value (one of them) that I want to access.
Basically, you can't. At least, not in any sensible way. Currently all that you have is a query. You don't actually have a collection of objects, you just have information about what you need to do to create those objects. It is the job of the query provider that you're currently in the process of writing to actually build the objects that the query defines and return them.
You've designed your program such that the query provider that creates the objects needs to have the already created objects already in order to properly build the query. It's impossible to already have the objects defined by the query that you haven't built yet. You've created a circular dependency for yourself.
It's important for you to provide the information needed to build the query somewhere other than in instances the objects that the query itself creates. Typically this is done with attributes on the properties, or by basing the query on the other existing C# metadata about the type itself. This type data exists, and is accessible to your query provider without needing any actual instances of the objects you're tasked with creating.
I'm adding this answer because I found two ways of extracting the value that I want. I want to thank Servey though for his answer as he was indeed correct about not doing it in any sensible way in that I had my code written.
What I found was two ways of going about this.
Using a generic translator class with a generic parameter that was the class type of the parameter that my lambda expression was wanting, and then using that generic parameter as the input parameter on the Func<object, T> delgate. This is the best and fastest way of doing it, as there is no dynamic operations going on during runtime.
var lambda = Expression.Lambda<Func<object, T>>(//Expressions here);
The second way I found is slower as it involves the Delegate.DynamicInvoke() method, but it does work.
var lambda = Expression.Lambda(member, (ParameterExpression)member.Expression);
var d = lambda.Compile();
return d.DynamicInvoke(member.Expression.Type.GetConstructors()[0].Invoke(new object[0]));
This will get the object's value but is costly due to the dynamic invoke.

Add properties to class dynamically C#

I want to add properties to a class dynamically and set values to them. Could someone point me in the right direction to some tutorials or articles or even better provide an example.
I have a base class which is called in a foreach loop. Inside this class I need to add up to 30 properties and set values to them.
This is the method that calls the class.
foreach (Class name in this.list)
{
ClassBeingCalled class = new ClassBeingCalled (name);
class.Populate();
this.newlist.Add(class);
}
Now inside the class being called, I need to create the 30 or so properties on the fly, which will be set in the "Populate" method of that class.
Like so...
foreach (PropertyToAssign count2 in listofproperties)
{
string name = "_nameofproperty" + count2.name
base.GetType().GetField(name, BindingFlags.NonPublic |
BindingFlags.Instance).SetValue(this, count2);
}
There are a few ways to approach this.
a) You use reflection to generate a class at runtime with whatever you need. You can always derive this generated class from a base class that contains Populate but I don't see the need.
b) If you're using C# 4.0+, you could use ExpandoObject, which allows you to set whatever properties you want for your needs. Note that these are not added as properties per se, as it uses the DLR which is all runtime-based. Depending on your needs, this may be fine; this is pretty much the same as approach c, but using the DLR.
c) You could use a backing dictionary and use an indexer, like so:
private Dictionary<string, object> _internalData = new Dictionary<string, object>();
public T this[string propName]
{
get {
return _internalData[propName];
}
set {
_internalData[propName] = value;
}
}
By using approach 3, you're actually indexing based on strings which is probably better based on your requirements... As you can do something along the lines of this:
foreach (PropertyToAssign count2 in listofproperties)
{
string name = "_nameofproperty" + count2.name;
this[name] = count2.value;
}
At the end of the day, it's probably best if you explain the problem you're trying to solve, as there may be a better way to approach it entirely.
It is not possible to add dynamic properties to a compiled class on the fly. You can only add dynamic properties to classes while building the class itself on the fly using Reflection.Emit
Your other option could be using a Dictionary or ExpandoObject (which is actually a dictionary). But for this option, you cannot access your dynamic properties using reflection.

Categories