Method that returns properties based on input? - c#

Is it possible, and not to stupid, to create a methods that returns only a select few properties from a large object based on the input?
I have a large object that I can retrieve. The problem is that it takes quite awhile to fill/generate the entire object. I would like a single method that can fill parts of that object based on what I send in.
Say that there are 100 properties in the object. In several cases i only need 1 of the properties of the object to do some checking, or a select few properties.
I can make separate methods to get that property only, but this quickly generates alot of very similar methods and it will be a pain to work with and maintain.
The properties in the object are a mix of simple and complex. Some of them are just boolean and strings while others make call to a DB to resolve custom objects from a Id on the object. For example retrieves a customer object based on the customer Id.
I want to do something like this:
public MyObject FillSelectProperties(guid Id, params string[] properties)
{
foreach(property in properties
FillProperty(property);
}
Or something like that.
Maybe use reflection? Or some other way that is more efficient.
Example:
var mo = FillSelectProperties(id, "Prop4", "Prop17", "Prop18");
if(mo.Prop4 == true)
//do something with mo.Prop17 and moProp18
I dont know if this is only wishful thinking that this is solvable without generating alot of specific methods.

Related

ASP.Net XUnit check if list of objects cointains a specific object

I am trying to add unit tests to my project. Some of these tests are checking if a list of objects does of does not contain an object. For checking if a list contains an object i've tried Assert.Contains(MyList, ExpectedObject), but it still gives an error that says that the list does not contain this object. Even when i debug the test i can see that the object is correctly added to the list.
The same happens with Assert.DoesNotContain(MyList, ExpectedObject). When i remove an item from the list and do this check it does say that it not in the list. But when i no longer remove the item, it still says that it is no longer in the list. Even though it is still in the list.
When i try it with a test list:List<string>. and do the same operations of adding and removing items, and then checking if these items are in the list or not. It does work.
Maybe Assert.Contains does not work for lists of objects. But the compiler does not give any errors. And i've also already checked if the ExpectedObject is the same type as the objects in the list.
Is there maybe another way of checking if an object is or isn't in a list.
any help is appreciated.
In your test, is ExpectedObject the actual object in the list or an object with the same values? In C# two objects with the same property values are not actually equal. I suspect this is why your test is failing. Two strings with the same value are considered equal because the string object implements the Equals method (and some more), like #dorukerenaktas points out.
There's multiple ways to go about this. The easiest is by checking if an object with the expected property values is in the collection.
There's an overload of Assert.Contains that allows you to specify a predicate, for example:
Assert.Contains(MyList, item => item.Id == expectedId)
Another option is to override the Equals method on your object, like #dorukerenaktas explains, but I would only recommend that if it really makes sense for your class. I would definitely not do that just so you can use this in a test.
Generally in Java and C# implementation of contains methods for object lists compare them by equals method. If equals method if not specified for the object by default it will look for object unique id or memory address, it means even if there were 2 objects with all same fields can be different. Because they created separately and allocated different ram addresses. If you want to compare objects override equals method. This will allow contains method to compare objects with each other using your custom comparison method.
Example:
Let say you have a Person object with fields like id, name, mail etc. If you want objects to be equal if their id's are same you can use:
// They are same person if their id is same
public override bool Equals(Object obj)
{
Person personObj = obj as Person;
if (personObj == null)
return false;
else
return idNumber.Equals(personObj.idNumber);
}
I have faced a similar problem before and I used fluentAssertions to solve it.
So for example if you have a list of objects called myList, this snipped should do the trick.
myList.Should().Contain(expectedItem);
There is more info on collections here: https://fluentassertions.com/collections/
The other option is to loop through the list and check if any of the objects are equal to your object. When doing this, if you use the ShouldBeEquivalentTo() method you will not need to check equality of every property. This is very useful if your object is large or nested, since this method checks each property recursively.
actual.Should().BeEquivalentTo(expected);
There is more information on this here: https://fluentassertions.com/objectgraphs/
I like using fluentAssetions because it makes my tests and assertions more readable, and also provides very clear messages when errors do occurs or assertions fail, so you find the problem faster.

C# custom file parsing with 2 delimiters and different record types

I have a (not quite valid) CSV file that contains rows of multiple types. Any record could be one of about 6 different types and each type has a different number of properties. The first part of any row contains the timestamp and the type of record, followed by a standard CSV of the data.
Example
1456057920 PERSON, Ted Danson, 123 Fake Street, 555-123-3214, blah
1476195120 PLACE, Detroit, Michigan, 12345
1440581532 THING, Bucket, Has holes, Not a good bucket
And to make matters more complex, I need to be able to do different things with the records depending on certain criteria. So a PERSON type can be automatically inserted into a DB without user input, but a THING type would be displayed on screen for the user to review and approve before adding to DB and continuing the parse, etc.
Normally, I would use a library like CsvHelper to map the records to a type, but in this case since the types could be different, and the first part uses a space instead of comma, I dont know how to do that with a standard CSV library. So currently how I am doing it each loop is:
String split based off comma.
Split the first array item by the space.
Use a switch statement to determine the type and create the object.
Put that object into a List of type object.
Get confused as to where to go now because i now have a list of various types and will have to use yet another switch or if to determine the next parts.
I don't really know for sure if I will actually need that List but I have a feeling the user will want the ability to manually flip through records in the file.
By this point, this is starting to make for very long, confusing code, and my gut feeling tells me there has to be a cleaner way to do this. I thought maybe using Type.GetType(string) would help simplify the code some, but this seems like it might be terribly inefficient in a loop with 10k+ records and might make things even more confusing. I then thought maybe making some interfaces might help, but I'm not the greatest at using interfaces in this context and I seem to end up in about this same situation.
So what would be a more manageable way to parse this file? Are there any C# parsing libraries out there that would be able to handle something like this?
You can implement an IRecord interface that has a Timestamp property and a Process method (perhaps others as well).
Then, implement concrete types for each type of record.
Use a switch statement to determine the type and create and populate the correct concrete type.
Place each object in a List
After that you can do whatever you need. Some examples:
Loop through each item and call Process() to handle it.
Use linq .OfType<{concrete type}> to segment the list. (Warning with 10k
records, this would be slow since it would traverse the entire list for each concrete type.)
Use an overridden ToString method to give a single text representation of the IRecord
If using WPF, you can define a datatype template for each concrete type, bind an ItemsControl derivative to a collection of IRecords and your "detail" display (e.g. ListItem or separate ContentControl) will automagically display the item using the correct DataTemplate
Continuing in my comment - well that depends. What u described is actually pretty good for starters, u can of course expand it to a series of factories one for each object type - so that you move from explicit switch into searching for first factory that can parse a line. Might prove useful if u are looking to adding more object types in the future - you just add then another factory for new kind of object. Up to you if these objects should share a common interface. Interface is used generally to define a a behavior, so it doesn't seem so. Maybe you should rather just a Dictionary? You need to ask urself if you actually need strongly typed objects here? Maybe what you need is a simple class with ObjectType property and Dictionary of properties with some helper methods for easy typed properties access like GetBool, GetInt or generic Get?

How to create the ability to apply a generic data source class

This is maybe something I know how to do or have already done it in the past. For some reason I am drawing a blank on how to wrap my head around it. This is more for learning as well as trying to implement something in my app.
I am using a set of third party controls. These controls offer a lot of functionality which is great. However, I want to be able to create a custom object that handle the logic/properties for the datasource of this control.
For example, there is a spreadsheet like object that I am using. You supply the spreadsheet like object some data and it pulls in your data. The problem here is that you need to set the columns, their data types, and other formatting/events as well as some logic to spit the data back to the user.
List<CustomClassWithProperties> dataSource
The custom class has some properties that will be translated to the columns. Like ProductName, Price, SalesDepartment, DatePurchased etc. This can be done by supplying the spreadsheet the columns and their data types each time. I want to be able to create a helper class that you just supply a list, a visible column list, and an editable column list and the data will fill in without any other issues.
Using the above list, I would imagine something similar to this:
DataHelperClass dtHlpr = new DataHelperClass(List<CustomClassWithProperties> data, List<string> visibleColumns, List<string> editableColumns)
This data helper class will take the data input list as the spreadsheet data source. It would then take the visibleColumns list and use that to set the visible rows, same for editableColumns.
Where I am running into a mental block (long week) is when I want to be able to reuse this. Let's say I have a List that has completely different properties. I would want my constructor for the data helper to be able to handle any List I send to it. Looking at whatever code I can get to for the third party controls, it appears that their data source is of type object.
Could someone point me in the right direction? I am thinking it has to do with generics and some interface implementation. I just honestly cannot think of where to start.
You can make the class itself generic:
public class DataHelperClass<T>
{
public DataHelperClass(List<T> data, ...) { ... }
}
DataHelperClass<CustomClassWithProperties> dtHlpr = new DataHelperClass<CustomClassWithProperties>(List<CustomClassWithProperties> data, List<string> visibleColumns, List<string> editableColumns)
You'd then perform your reflection against typeof(T).
I'd also be tempted to use IEnumerable<T> rather than List<T> if possible, but that's a matter of preference, more or less.
This is similar to using a simple List<object>, except that it enforces that all objects in the list inherit from the same type (which might well be object), so you get some more type-checking than you otherwise would.
You mentioned interfaces, I don't see any reason here to include that (from what you've told us, at least), but you can certainly make a generic interface via the same syntax.

Is it possible to create a class template and select a C# property when the function is called?

Does anyone know if the following is possible to pass in a List<> of objects to a function and specify which property the function should use within each object that its working with ?
I have a class that works with a specific property of an object throughout the class, but I dont want to create multiple copies of the same class to work with different properties of that object. I thought about using Linq, but I dont see a way to specify which property to use in other functions of the manipulation class.
I was thinking there has to be a more elegant way to do this instead of creating the same class to handle each property. I thought about using Reflection to tell the function which property to work with but that gets ugly really quick
Example psuedo code :
class Store
{
int amount;
int id;
int serial;
}
class AggregationMethods
{
bool Has3Values( List<Store> places /* some other param to specify which property to use*/)
{
// do something with Store.amount or Store.id
}
// other functions to work with Store.amount or Store.id or Store.serial
}
In your case, they're all int values - so you could just retain a Func<Store, int> or pass it into each method. It becomes slightly harder if you need to work over multiple types, but we don't really have enough information to comment further.
It's also not clear whether you would expect two have multiple instances of AggregationMethods (e.g. one for amounts, one for IDs etc) or whether these would really be static methods. If you're using instances, then you could keep the projection as a member variable, and apply it within each method.
It's worth noting that the properties you've given probably don't really make sense to apply the same aggregations - for example, while summing amounts makes sense, it's meaningless to sum IDs.

Linq to DataTable without enumerating fields

i´m trying to query a DataTable object without specifying the fields, like this :
var linqdata = from ItemA in ItemData.AsEnumerable()
select ItemA
but the returning type is
System.Data.EnumerableRowCollection<System.Data.DataRow>
and I need the following returning type
System.Data.EnumerableRowCollection<<object,object>>
(like the standard anonymous type)
Any idea?
Thanks
If I understand you correctly, you'd like to get a collection of objects that you don't need to define in your code but that are usable in a strongly typed fashion. Sadly, no you can't.
An anonymous type seems like some kind of variant or dynamic object, but it is in fact a strongly typed class that is defined at compile time. .NET defines the type for you automatically behind the scenes. In order for .net to be able to do this, it has to have some clue from the code with which to infer the type definition. It has to have something like:
from ItemA in ItemData.AsEnumerable()
select ItemA.Item("Name"), ItemA.Item("Email")
so it knows what members to define. There's no way to get around it, the information has to logically be there for the anonymous type to be defined.
Depending on why exactly your are trying to do this, there are some options.
If you want intellisense while still encapsulating your data access, you can return xml instead of a datatable from your encapsulated data access class. (You can convert data tables to xml very easily. You'll want to use the new System.Xml.Linq classes like the XElement. They're great!) Then you can use VS2008's ability to create an xsd schema from xml. Then use/import that schema at the top of your code page, and you have intellisense.
If you have to have an object an with properties for your data, but don't want to define a class/structure for them, you'll love the new dynamic objects coming in C#4.0/VB10. You have object properties based on what the sql returns, but you won't have intellisense. There is also a performance cost to this, but (a) that might not matter for your situation and (b) it actually is not so bad in some situations.
If you're just trying to avoid making a lot of classes, consider defining structs/structures on the same code file, beneath your class definition. When you add more columns to your result set, it's easy to adjust a struct with more public fields.
In short you can have any two of the following three: (a) dynamic, (b) strontly-typed objects, (3) intellisense. But not all three.
There is one way to accomplish what you want, but it required knowledge of dynamic linq. You would build the query during run-time and then use it. I am no expert and have never really played around with it, but here is a link to Scott Guthrie's blog about it - Dynamic Linq. Hope that helps.
Wade

Categories

Resources