Check object values with list of properties (reflection) - c#

I currently working on an dynamic upload module. The idea is to only define the file and the data contract for each new file. Currently I'm using reflection with 2 foreach, this is some heavy code to do this. As you can see in the code I have my object containing the csv file and 2 other lists. These two lists contains all the properties of the object where I would like to do data validation on.
var myCustomObjects = CsvSettings(new CsvReader(readFile, config)).GetRecords<MyCustomObject>();
var decimalProprties = GetPropertyNames<MyCustomObject>(typeof(decimal)).ToList();
var dateProprties = GetPropertyNames<MyCustomObject>(typeof(DateTime)).ToList();
foreach (var myCustomObject in myCustomObjects)
{
foreach (var dateProperty in dateProprties)
{
var value = myCustomObject.GetType().GetProperty(dateProperty).GetValue(myCustomObject, null);
Console.WriteLine(value); //code to check and report the value
}
Console.WriteLine(myCustomObject.Een + "|" + myCustomObject.Twee + "|" + myCustomObject.Drie);
}
How can I do this with an expression or even another way to have so less heavy code?

The code seems fine as-is. You could perhaps simplify it a little by using a method that returns Key/Value pairs for all public properties of a certain type, like so (error handling elided for brevity):
public static IEnumerable<KeyValuePair<string, T>> PropertiesOfType<T>(object myObject)
{
var properties =
from property in myObject.GetType().GetProperties()
where property.PropertyType == typeof(T) && property.CanRead
select new KeyValuePair<string, T>(property.Name, (T)property.GetValue(myObject));
return properties;
}
Then you can avoid the additional call to GetProperty() in your inner loop:
foreach (var myCustomObject in myCustomObjects)
{
foreach (var dateProperty in PropertiesOfType<DateTime>(myCustomObject))
{
Console.WriteLine(dateProperty.Value); // code to check and report the value.
}
}
Also note that you don't seem to need the .ToList() calls.

Related

HtmlEncode List<int, string> In MVC

I have a c# class object that is List<int,string> I need to make sure the list's string variable is HtmlEncoded before passing back to an MVC controller (where I will later need to decode) but I'm having difficulty because the company's custom libraries are written in such a way that I have a hard time manipulating the code.
In this particular scenario, the data field is embedded into a SQL statement that is converted to the List<int,string> object. Before this List<int,string> is passed back, I need to use WebUtility.HtmlEncode on the string variable "GroupName":
public List<DatasetModel> GetMembers(List<int> groupIds)
{
using (var work in unitOfWorkFactory())
{
return work.DataContext.Query.Read<DatasetModel>(
$#SELECT {nameof(TableOne.GroupId)
, {(nameof(TableOne.Name))} as GroupName
FROM {this._tableProvider.GlobalTable<TableOne>()}
WHERE {nameof(TableOne.GroupId)} {groupIds.ToSqlInClause()}"
).ToList();
)
}
}
I've tried creating extension methods and something like the following but get type conversion errors, etc, that lead me to write rudimentary for loops and cast() and such that are not appropriate:
List<DatasetModel> returnList = model.Select(x => new DatasetModel{x.GroupId, WebUtility.HtmlEncode(x.Name)}).ToList();
FOLLOW-UP:
Here is what I've had to do to achieve the goal. I don't like it because I am using a foreach loop in the called method. I haven't been able to consistently understand / resolve errors involving 'initializer errors' and List vs generic lists:
public List<DatasetModel> GetMembers(List<int> groupIds)
{
using (var work in unitOfWorkFactory())
{
return EncodeList(work.DataContext.Query.Read<DatasetModel>(
$#SELECT {nameof(TableOne.GroupId)
, {(nameof(TableOne.Name))} as GroupName
FROM {this._tableProvider.GlobalTable<TableOne>()}
WHERE {nameof(TableOne.GroupId)} {groupIds.ToSqlInClause()}"
).ToList();
)
}
}
private static List<DatasetModel> EncodeList(List<DatasetModel> list)
{
var returnList = new List<DatasetModel>();
foreach (var l in list)
{
var m = new DatasetModel(attributeId: l.attributeId, attributeName: WebUtility.HtmlEncode(l.attributeName));
returnList.Add(m);
}
return returnList;
}

How to access the values in a dynamic dictionary in C#?

I have a dictionary which is dynamically generated. In the dictionary, for a single Key, there are multiple values. I am trying to access one of the values in those multiple values. My code so far:
var result = new Dictionary<string, object>();
var dictionary = deserialisedResult as IDictionary<string, object>;
foreach (var item in dictionary)
{
result.Add(item.Key, item.Value);
}
object o = result;
string[] names = o.GetType().GetProperties().Select(p => p.Name).ToArray();
foreach (var prop in names)
{
object propValue = o.GetType().GetProperty(prop).GetValue(o, null);
var value = propValue.GetValue(o,null);
}
But this is not working.
I need to get the values for 'resource'.
When I add watch, I see it nested as such:
Following line is causing issue out here:
string[] names = o.GetType().GetProperties().Select(p => p.Name).ToArray();
GetType() for Object base class type will not yield a Type, which can provide the PropertyInfo[], that you are looking for, even otherwise you are trying to run it for Dictionary<string,object> type, which anyway doesn't have properties to help find the relevant information. For it the Type would always be Dictionary
What you need is fetch the key collection from Dictionary and use them to fetch the values stored in the Dictionary
foreach (var key in result.Keys)
{
var value = result[key];
}
Solution is based on code provided in the question, I am not sure if you have further requirements

How to simplify multiple nested foreachs in c#

Basically I have a method that is passed a list of custom objects. I'm using C#. Each of these contains a name and another list of other custom objects, I'll call these subObjects. These each have a name and a list of strings. I need to loop through all the strings, but keep track of the names of the parent object and subject for error logging purposes. Is there a cleaner, nicer way to do this than nesting foreachs?
foreach (var obj in listOfObjects)
{
foreach (var subObj in obj.subObjects)
{
foreach (var aString in subObj.strings)
{
if (some condition applies)
{
//log error that includes obj, subObj, and subSubObj names, and aString.
}
}
}
}
You can write a LINQ query to get all error cases
var errors = from obj in listOfObjects
from subObj in obj.subObjects
from aString in subObj.strings
where /* your condition */
select new { obj, subObj, aString };
and than iterate over them only:
foreach(var errorCase in errors)
{
// log your error
}
or get the first one:
var error = errors.FirstOrDefault();
depending on your needs.
Adding to MarcinJuraszek answer, if linq to objects is preferred...
var errors = listOfObjects
.SelectMany(obj => obj.subObjects
.SelectMany(subObj => subObj.strings
.Where(r => /* your condition */)
.Select(aString => new { obj, subObj, aString })));
But there's nothing wrong with the code you posted. Clearly, yours is easier to follow at a quick glance.

C# tree data structure, making output

I've made my own tree data structure via classes.
Now I'm stuck with really basic stuffs. I need to make output tab delimited file from data in my List <MainTreeNode>.
I think that recursion is only way?!
Tree is N-tree, and output have first row as header and other rows are values.
Tree:
MSG (MainTreeNode)
MainParam (Must have prop NAME, doesn't have to have prop VALUE)
SubParam1 (Must have prop NAME, must have prop VALUE)
SubParam2 (Must have prop NAME, doesn't have to have prop VALUE)
SubSubParam2.1 (Must have prop NAME, must have prop VALUE)
etc.
Or:
Message : Name
Param1 : ValueV1 (VALUE must, because it doesn't have children)
Param2
Param2.1 : ValueV2
Param2.2 : Value
Param2.2.1 : ValueV3
Param2.2.2 : ValueV4 ...etc.
And output have to be like this (first line is header):
Param1|Param2/Param2.1|Param2/Param2.2/Param2.2.1|Param2/Param2.2/Param2.2.2
ValueV1|ValueV2|ValueV3|ValueV4
...
So I need probably List for header and for values but I don't know how to implement that in recursion way (or any another).
Some of unfinished code:
public void PrintToTabFile(List<Message> messages, List<string> parameters)
{
foreach (string s in parameters)
{
using (StreamWriter streamWriter = new StreamWriter(#"C:\temp\" + s + ".xls"))
{
streamWriter.Write("No.\tMsgName\tMsgData1\tMsgData2\tMsgData3");
var msg = messages.Where(x => x.Parameters.Where(p => p.ParameterName == s).Count() == 1);
List<string> headers = new List<string>();
List<string> values= new List<string>();
//... Stuck!!!
}
}
}
private void Recursion(Parameter parameter, List<string> headers, List<string> values)
{
if (parameter.SubParameters.Count == 0)
{
int index = headers.IndexOf(parameter.ParameterName);
values[index] = parameter.ParameterValue;
}
else
{
foreach (Parameter p in parameter.SubParameters)
{
Recursion(p, headers, values);
//and Stuck Probably here or before recursion call
}
}
}
I won't claim that I really know what you are asking, but still I'll give it shot. To me this seems like a very basic recursion to traverse a tree structure with some weird output while you are doing it.
Try it like this:
1. Make an interface for all your classes called INode. This interface should contain the typical things like List Children, INode Parent etc.
2. Make all your classes implement this interface (or let them inherit a base class that does this)
3. Now start with your base clase and traverse recursively over all Children using the Children property and generate your output.
This should do the trick I guess. (Sorry, no VS here to put up some real code)
BTW: you'll probably find a ton of posts about this on stackoverflow already.

How to perform a deep copy of an object not marked as serializable (in C#)?

I am attempting to create a Clipboard stack in C#. Clipboard data is stored in System.Windows.Forms.DataObject objects. I wanted to store each clipboard entry (IDataObject) directly in a Generic list. Due to the way Bitmaps (seem to be) stored I am thinking I need to perform a deep copy first before I add it to the list.
I attempted to use Binary serialization (see below) to create a deep copy but since System.Windows.Forms.DataObject is not marked as serializable the serialization step fails. Any ideas?
public IDataObject GetClipboardData()
{
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, Clipboard.GetDataObject());
memoryStream.Position = 0;
return (IDataObject) binaryFormatter.Deserialize(memoryStream);
}
I wrote the code below for another question and maybe it could come in useful for you in this scenario:
public static class GhettoSerializer
{
// you could make this a factory method if your type
// has a constructor that appeals to you (i.e. default
// parameterless constructor)
public static void Initialize<T>(T instance, IDictionary<string, object> values)
{
var props = typeof(T).GetProperties();
// my approach does nothing to handle rare properties with array indexers
var matches = props.Join(
values,
pi => pi.Name,
kvp => kvp.Key,
(property, kvp) =>
new {
Set = new Action<object,object,object[]>(property.SetValue),
kvp.Value
}
);
foreach (var match in matches)
match.Set(instance, match.Value, null);
}
public static IDictionary<string, object> Serialize<T>(T instance)
{
var props = typeof(T).GetProperties();
var ret = new Dictionary<string, object>();
foreach (var property in props)
{
if (!property.CanWrite || !property.CanRead)
continue;
ret.Add(property.Name, property.GetValue(instance, null));
}
return ret;
}
}
However I don't think this will be the final solution to your problem though it may give you a place to start.
Look up the docks for Serializable and find the stuff about serialization helpers. You can wrap the bitmap in your own serialization code the integrates with the .net framework.
Copy of my answer to: difference between DataContract attribute and Serializable attribute in .net
My answer fits much better here than there, although above question ends with:
"... or maybe a different way of creating a deepclone?"
I once did some inspection to an object structure via Reflection to find all assemblies required for deserialization and serialize them alongside for bootstrapping.
With a bit of work one could build a similar method for deep copying. Basically you need a recursive method that carrys along a Dictionary to detect circular references. Inside the method you inspect all fields about like this:
private void InspectRecursively(object input,
Dictionary<object, bool> processedObjects)
{
if ((input != null) && !processedObjects.ContainsKey(input))
{
processedObjects.Add(input, true);
List<FieldInfo> fields = type.GetFields(BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic );
foreach (FieldInfo field in fields)
{
object nextInput = field.GetValue(input);
if (nextInput is System.Collections.IEnumerable)
{
System.Collections.IEnumerator enumerator = (nextInput as
System.Collections.IEnumerable).GetEnumerator();
while (enumerator.MoveNext())
{
InspectRecursively(enumerator.Current, processedObjects);
}
}
else
{
InspectRecursively(nextInput, processedObjects);
}
}
}
}
To get it working you need to add an output object and something like System.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type type) to create the most shallowest copy (even without copying references) of each field's value. Finally you can set each field with something like field.SetValue(input, output)
However this implementation does not support registered event handlers, which is _un_supported by deserializing, too. Additionally each object in the hierarchy will be broken, if its class' constructor needs to initialize anything but setting all fields. The last point only work with serialization, if the class has a respective implementation, e.g. method marked [OnDeserialized], implements ISerializable,... .

Categories