How can i add a property to object during the a run time at C#? - c#

I have two different lists. I want to combine these list in an object. I don't know the property names in these lists, which is why I cannot create a class in advance.
public class exampleConfigProperty
{
public string PropertName { get; set; };
public string PropertValue { get; set; };
}
public class exampleFile
{
public string config1 { get; set; };
}
List<exampleConfigProperty> myList = new List<exampleConfigProperty>();
myList.add(new exampleConfigProperty {
PropertName = "Config_Property_Name",
PropertValue = "Config Property Value"
});
List<exampleFile> myListTwo = new List<exampleFile>();
myListTwo.add(new exampleFile {
config1 = "Config Value"
});
I tried to figure out if is there any way I can use the code below:
var obj = new object();
foreach(var item in myList)
{
obj.addProperty(item.PropertName, item.PropertValue );
}
foreach(var item in myListTwo)
{
obj.addProperty(nameof(item.config1), item.config1 );
}
In conclusion I try to create an object instance by using two lists,
for example:
var resut = new {
Config_Property_Name = "Config Property Value",
config1 ="Config Value"
}
dynamic type does not work so what should I do to get an object instance by using two lists?

Since you just want to make a JSON I think would fit your criteria:
var test = new Dictionary<string, string>(); //<string, object> for mixed types of values
test["key1"] = "value1";
test["key2"] = "value2";
var result = JsonConvert.SerializeObject(test); //indented for readability of result
// result:
// {
// "key1": "value1",
// "key2": "value2"
// }

Related

Merge list of objects using linq in C#

I have a class defined below
public class ResultClass()
{
public HashSet<string> VerifiedResults { get; private set; }
public HashSet<string> UnverifiedResults { get; private set; }
bool IsBlocked {get; private set; }
}
If I have a list containing items for ResultClass, for eg., List<ResultClass>() , how can I combine the results into a single ResultClass object using LINQ.
Is a way to do what my code below does, but with LINQ, instead?
var finalResult = new ResultClass();
foreach(var item in listOfResultClass)
{
finalResult.VerifiedResults.Union(item.VerifiedResults);
finalResult.UnverifiedResults.Union(item.UnverifiedResults);
finalResult.IsBlocked = item.IsBlocked;
}
This can be achieved using the LINQ Aggregate function, as can be seen in following example:
public class ResultClass
{
public HashSet<string> VerifiedResults { get; set; } = new();
public HashSet<string> UnverifiedResults { get; set; } = new();
public bool IsBlocked { get; set; } = false;
}
internal class Program
{
private static void Main()
{
var results = GetResults();
var finalResult = results.Aggregate(new ResultClass(), (r, next) =>
{
r.IsBlocked = r.IsBlocked || next.IsBlocked;
r.VerifiedResults.UnionWith(next.VerifiedResults);
r.UnverifiedResults.UnionWith(next.UnverifiedResults);
return r;
});
}
private static List<ResultClass> GetResults()
{
return new List<ResultClass>()
{
new ResultClass()
{
VerifiedResults = new HashSet<string>{"first", "second" },
UnverifiedResults = new HashSet<string>{"third" },
IsBlocked = false
},
new ResultClass()
{
VerifiedResults = new HashSet<string>{"first", "fourth" },
UnverifiedResults = new HashSet<string>{"fifth" },
IsBlocked = true
},
new ResultClass()
{
VerifiedResults = new HashSet<string> (),
UnverifiedResults = new HashSet<string>{"sixt", "seventh" },
IsBlocked = false
}
};
}
}
A few remarks:
I adapted your ResultClass to remove compiler errors and to make it possible to initialize a list of them easily.
for the 'IsBlocked property, I used the logical OR of all the individual IsBlocked properties.
You should use UnionWith rather than Union in this case.
It might be a good idea to think about possible conflicts where the same string occurs in different ResultClass instances, both in 'verified' and 'unverified' properties. It may be necessary to adapt the accumulator lambda expression to get the results you want.
As #iSR5 mentioned, you can use SelectMany. I am not sure how do you plan to assign the IsBlocked, but this seems to behave like your code:
var result = new ResultClass()
{
VerifiedResults = new HashSet<string>(results.SelectMany(x => x.VerifiedResults)),
UnverifiedResults = new HashSet<string>(results.SelectMany(x => x.UnverifiedResults)),
IsBlocked = results.LastOrDefault().IsBlocked,
};
Also, please read #Johan Donne comments.

Creating an anonymous object who must have the dot in Key name and put it inside another anonymous object

I'm making a JSON body for an elasticsearch query.
I have this dynamic:
var hlBodyText = new
{
bodyText = new { }
};
But there's a case in which the name must be bodyText.exact = new { }, but obviously I'm not allowed to do it and return the error message:
Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access.
There's a way to make that value name with the dot char?
EDIT
Furthermore, I have to put this object inside another object, like this:
var fieldsInner = new
{
hlBodyText.bodyText
};
What could be the best way to get this result but with the property name set with the dot?
EDIT #2
I created a class with all my parameters beacause I thought the JsonProperty attribute could help me.
internal class ElasticSearchHighlightsModel
{
[JsonProperty("bodyText")]
public object bodyText { get; set; }
[JsonProperty("title")]
public object title { get; set; }
[JsonProperty("shortDescription")]
public object shortDescription { get; set; }
[JsonProperty("bodyText.exact")]
public object bodyTextExact { get; set; }
[JsonProperty("title.exact")]
public object titleExact { get; set; }
[JsonProperty("shortDescription.exact")]
public object shortDescriptionExact { get; set; }
}
then in my method i have a condition for which I have to use some params or others.
// ...some code...
else
{
var hlBodyText = new ElasticSearchHighlightsModel() { bodyTextExact = new { } };
var hlTitle = new ElasticSearchHighlightsModel() { titleExact = new { } };
var hlShortDescription = new ElasticSearchHighlightsModel() { shortDescriptionExact = new { } };
var fieldsInner = new
{
hlBodyText.bodyTextExact,
hlTitle.titleExact,
hlShortDescription.shortDescriptionExact,
};
var fieldsContainer = new
{
pre_tags = preTags,
post_tags = postTags,
fields = fieldsInner,
};
return fieldsContainer;
}
But the fieldsInner object have the parameter names (bodyTextExact, titleExact etc...), not the JsonProperty attribute ones.
It seems this you are looking for,later u convert dictionary to json
Dictionary<string,object> obj=new Dictionary<string,object>();
obj["bodyText.exact"]=new object{};
Solved using Dictionary, then passed it inside an anonymous type obj:
IDictionary highlitsFieldsContainer = new Dictionary<string, object>();
// ... some code
highlitsFieldsContainer["bodyText.exact"] = new { };
highlitsFieldsContainer["title.exact"] = new { };
var fieldsContainer = new
{
fields = highlitsFieldsContainer,
};
// OUTPUT: fieldsContainer = { fields = { bodyText.exact = {}, title.exact = {} } }
And used a RouteValueDictionary class to read that values when elasticsearch send his response.
RouteValueDictionary _res = new RouteValueDictionary(dynamicResponse.highlights);
if (_res["shortDescription.exact"] != null)
{
// ...
}
You seem to be creating an anonymous type (not "dynamic") and wanting to serialize it with a different name that is not valid in C#. To do that you'll need to use a named type and use the JsonProperty
attribute:
internal class HlBodyText
{
[JsonProperty("bodyText.exact")]
public DateTime bodyText { get; set; }
}
and create an instance of it:
var hlBodyText = new HlBodyText()
{
bodyText = new { }
};

FluentAssertions - how make ShouldBeEquivalentTo compare empty and null as equal

I am using Fluent Assertion library as part of my unit tests for some custom serialization code and I am looking for a way to force ShouldBeEquivalentTo to compare as equal a null and empty list.
Basically, my tests look something like:
[Test]
public void Should_be_xxx()
{
ClassWithList one = new ClassWithList { Id = "ten", Items = null };
string serialized = Serialize(one);
ClassWithList two = Deserialize(serialized);
two.ShouldBeEquivalentTo(one);
}
However, one of the features of the Deserialize method is that if a collection type is missing in the input data, it sets the property on the deserialized class to an empty list, rather than null. So, very simplified, I end up with a situation where in instance two, Items = new List<string> rather than null.
Obviously, I could set one.Items = new List<string>() before comparing, but in reality I have a large number of complex domain objects that I am asserting in these methods and I am looking for a general solution. To put it another way, does anyone know how to make the following test pass:
public class ClassWithList
{
public string Id { get; set; }
public List<string> Items { get; set; }
}
[Test]
public void Should_be_xxx()
{
ClassWithList one = new ClassWithList { Id = "ten", Items = null };
ClassWithList two = new ClassWithList { Id = "ten", Items = new List<string>() };
two.ShouldBeEquivalentTo(one);
}
To put it another way, I am looking to apply the following test to all collections in a class X as part of comparing equivalence:
if (subject.Items == null)
{
expected.Items.Should().BeEmpty();
}
else
{
expected.Items.Should().BeEquivalentTo(subject.Items);
}
Based on the information from Dennis above, I was able to solve this will the following actual code:
public class ClassWithList
{
public string Id { get; set; }
public List<string> Items { get; set; }
public List<ClassWithList> Nested { get; set; }
}
[TestClass]
public class Test
{
[TestMethod]
public void Should_compare_null_to_empty()
{
ClassWithList one = new ClassWithList { Id = "ten", Items = null, Nested = new List<ClassWithList> { new ClassWithList { Id = "a" } } };
ClassWithList two = new ClassWithList { Id = "ten", Items = new List<string>(), Nested = new List<ClassWithList> { new ClassWithList { Id = "a", Items = new List<string>(), Nested = new List<ClassWithList> { } } } };
two.ShouldBeEquivalentTo(one, opt => opt
.Using<IEnumerable>(CheckList)
.When(info => typeof(IEnumerable).IsAssignableFrom(info.CompileTimeType)));
}
private void CheckList(IAssertionContext<IEnumerable> a)
{
if (a.Expectation == null)
{
a.Subject.Should().BeEmpty();
}
else
{
a.Subject.ShouldBeEquivalentTo(a.Expectation, opt => opt
.Using<IEnumerable>(CheckList)
.When(info => typeof(IEnumerable).IsAssignableFrom(info.CompileTimeType)));
}
}
}
You'll have to implement a custom 'IEquivalencyStep' or u.se 'options.Using(custom action).WhenTypeIs(predicate).
Create an IAssertionRule:
public class EnumerableNullEmptyEquivalenceRule : IAssertionRule
{
public bool AssertEquality(IEquivalencyValidationContext context)
{
// not applicable - return false
if (!typeof(IEnumerable).IsAssignableFrom(context.SelectedMemberInfo.MemberType)) return false;
return context.Expectation == null && ((IEnumerable)context.Subject).IsNullOrEmpty();
}
}
Then apply to your BeEquivalentTo call:
actual.Should().BeEquivalentTo(expected, opt => opt.Using(new EnumerableNullEmptyEquivalenceRule()));

Create Json Array with ServiceStack

Quite new to .NET. Still haven't gotten the hang of how to do dictionaries, lists, arrays, etc.
I need to produce this JSON in order to talk to SugarCRM's REST API:
{
"name_value_list": {
"assigned_user_name": {
"name": "assigned_user_name",
"value": "joe"
},
"modified_by_name": {
"name": "modified_by_name",
"value": "jill"
},
"created_by_name": {
"name": "created_by_name",
"value": "jack"
}
}
}
from this C# POCO, which plays nicely with ServiceStack:
public class lead {
public string assigned_user_name { get; set; }
public string modified_by_name { get; set; }
public string created_by_name { get; set; }
}
I have to do this sort of conversion for lots of different classes, so I don't think it's wise to create another strongly typed class (ala Costomising the serialisation/serialised JSON in service stack)
I've looked through the ServiceStack docs, but maybe I missed an example of this somewhere.
How do I build this JSON in a way that I can extend to other ServiceStack POCOs?
This produces the right JSON:
Dictionary<string, Dictionary<string, string>> nameValues = new Dictionary<string, Dictionary<string, string>>();
// Deal with all the properties on the object
IList<PropertyInfo> props = new List<PropertyInfo>(this.GetType().GetProperties());
foreach (PropertyInfo prop in props)
{
Dictionary<string, string> nameValue = new Dictionary<string, string>();
nameValue.Add("name", prop.Name);
object propValue = prop.GetValue(this, null);
if (propValue == null)
{
nameValue.Add("value", string.Empty);
}
else
{
nameValue.Add("value", prop.GetValue(this, null).ToString());
}
nameValues.Add(prop.Name, nameValue);
}
Dictionary<string, object> nameValuesArray = new Dictionary<string, object>();
nameValuesArray.Add("name_value_list", nameValues);
string jsonString = JsonSerializer.SerializeToString<Dictionary<string, object>>(nameValuesArray);
The reflection stuff is so that I can use it on any object later.
It's just a matter of constructing the right dictionary for the desired JSON output - in this case a dictionary -> dictionary -> dictionary. Trial and error... :/
Update
Altered it slightly (thanks paaschpa) to use a generic NameValue class because Dictionaries look ugly. I also got the requirements wrong. The JSON should be this:
[
{
"name": "id",
"value": "60e03cb3-df91-02bd-91ae-51cb04f937bf"
},
{
"name": "first_name",
"value": "FancyPants"
}
]
which you can do like this:
public class NameValue
{
public string name { get; set; }
public string value { get; set; }
}
public class Lead
{
public string assigned_user_name { get; set; }
public string modified_by_name { get; set; }
public string modified_user_name { get; set; }
public List<NameValue> toNameValues()
{
List<NameValue> nameValues = new List<NameValue>();
IList<PropertyInfo> props = new List<PropertyInfo>(this.GetType().GetProperties());
foreach (PropertyInfo prop in props)
{
NameValue nameValue = new NameValue();
object propValue = prop.GetValue(this, null);
if (propValue != null && !String.IsNullOrEmpty(propValue.ToString()))
{
nameValue.name = prop.Name;
nameValue.value = propValue.ToString();
nameValues.Add(nameValue);
}
}
return nameValues;
}
}
I'm leaving my original question as is (and my above answer) because it's still a legit example and proper JSON.
Well, I don't think .NET dictionaries, lists, arrays, etc. will be helpful since the JSON you listed doesn't appear to have any arrays (square brackets) it in. I'm guessing most .NET JSON serializers will use square brackets when it hits these types. So, I think this leaves creating your own classes or doing some type of 'string magic' to produce to JSON you need.
Not exactly sure how you are using ServiceStack to talk to SugarCRM, but doing something like below should have ServiceStack.Text.JsonSerializer produce the JSON string you listed.
public class NameValue
{
public string name { get; set; }
public string value { get; set; }
}
public class Lead
{
public NameValue assigned_user_name { get; set; }
public NameValue modified_by_name { get; set; }
public NameValue created_by_name { get; set; }
}
public class LeadRequest
{
public Lead name_value_list { get; set; }
}
public void JsonTest()
{
var req = new LeadRequest
{
name_value_list = new Lead
{
assigned_user_name = new NameValue {name = "assigned_user_name", value = "joe"},
modified_by_name = new NameValue {name = "modified_by_name", value = "jill"},
created_by_name = new NameValue {name = "created_by_name", value = "jack"}
}
};
var jsonReq = ServiceStack.Text.JsonSerializer.SerializeToString(req);
}
You could create a custom serializer for the lead class.
JsConfig<lead>.SerializeFn = lead => {
// Use reflection to loop over the properties of the `lead` object and build a dictionary
var data = new Dictionary<string, object>();
foreach (var property in typeof(lead).GetProperties()) {
data[property.Name] = new {
name: property.Name,
value: property.GetValue(lead, null);
};
}
return data.ToJson();
};
You could make this generic by having all classes that you want to serialize in this way implement a marker interface, for example ISugarCrmRequest, and register this custom serializer for all implementations of that interface.

compare different type of list in c#

i have two list one is string list and other one is list of one class.that class contain some properties like soid,itemname,qty etc and its value also..string list and class list have some common property .so i wanted to check the string list with class list and add common values to one dictionary.
public class Input
{
public string soid { get; set; }
public string itemname { get; set; }
public int qty { get; set; }
}
list<Input> inputclass=new list<Input>();//inputclass list
List<string> metadata=new List<string>();//string list
metadata.Add("itemname");
metadata.Add("soid");
metadata.Add("qty");
so i wanted to compare the class member name with string list name
Not sure if I understood you 100% correctly, but given the following input:
var inputclass= new List<Input>() {
new Input(){ soid="123", itemname="Bar", qty=123 },
new Input(){ soid="777", itemname="Foo", qty=999 }
};
List<string> metadata=new List<string>() { "itemname", "soid", "qty" };
you can use the .ToDictionary() and .GetProperty() methods like this
Type t = typeof(Input);
var result = metadata.ToDictionary(i => i, i => inputclass.Select(c => t.GetProperty(i).GetValue(c)));
to create a dictionary that will look like
EDIT:
If metadata can contain values that are not properties of Input, the following would be save:
var result = metadata.Select(i => t.GetProperty(i))
.Where(i => i != null)
.ToDictionary(i => i.Name, i => inputclass.Select(c => i.GetValue(c)));
If I understood it right, you want to compare the type itself, not the instances inside that list.
You could do it this way:
List<string> metadata = new List<string>();//string list
metadata.Add("itemname");
metadata.Add("soid");
metadata.Add("qty");
metadata.Add("yada");
var result = from str in metadata
join prop in typeof(Input).GetProperties() on str equals prop.Name
select str;
foreach (string prop in result)
{
Console.WriteLine(prop);
}
Now, if you have a List of T unknown objects and want to match each with the metadata, tell me and I'll help you.
EDIT based on your comment: when we get the common name between list<input> and string how will get the value of corresponding member of the class.now you return only common names r8..?
You could do it like this. Suppose you have these two classes:
public class Input
{
public string soid { get; set; }
public string itemname { get; set; }
public int qty { get; set; }
}
public class Yada : Input
{
public string yada { get; set; }
}
So Input has 3 of the 4 properties, and Yada class has all 4.
Then suppose we have a list of objects:
List<Input> inputclass = new List<Input>();//inputclass list
inputclass.Add(new Input() { itemname = "test",soid="myId",qty=10 });
inputclass.Add(new Yada() { itemname = "test2",soid="myId2", yada = "woo",qty=20 });
You could get all the matching properties from the objects, including their current values, with this code:
var result = inputclass.Select(
input => (from str in metadata
join prop in input.GetType().GetProperties()
on str equals prop.Name
select new { Obj = input, Prop = str, Value = prop.GetValue(input, null) }))
.SelectMany(i => i)
.GroupBy(obj => obj.Obj);
foreach (var obj in result)
{
Console.WriteLine(obj.Key);
foreach (var prop in obj)
{
Console.WriteLine(prop.Prop + ":" + prop.Value);
}
Console.WriteLine();
}
Console.ReadKey();
Here is my input:
Just on a note, be careful when using GetValue: you'll have to do slight changes for it to work with Indexers, for example.
Using this ReflectionExt.GetAttr you can do something like this:
var dict = new Dictionary<string, List<string>>();
foreach(var listItem in inputclass)
{
foreach(var metaItem in metadata)
{
try
{
var value = ReflectionExt.GetAttr(listItem, metaItem);
if (dict[metaItem] == null)
dict[metaItem] = new List<string>();
if (!dict[metaItem].Contains(value)) // Add only if not exists
dict[metaItem].Add(value);
}
catch
{
;
}
}
}

Categories