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

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 { }
};

Related

Populate a C# array like a multi-dimensional array

I have a class that contains some properties:
public class PossibleSettingsData
{
public int Value { get; set; }
public string Definition { get; set; }
public object Meaning { get; set; }
}
and I have an array of this class and I want to instantiate it like a multi-dimensional array:
var PossibleSettings=new PossibleSettingsData[]
{
{ 5 ,"4800 baud", 4800}, \\It means I want to Value=5 and Definition="4800 baud" and Meaning=4800
{ 6 ,"9600 baud", 9600},
{ 7 ,"19200 baud" ,19200}
};
what changes do I have to make in PossibleSettingsData class to do this? Is it at all possible?
I have seen something like this when I want populate a Dictionary<,> so I think maybe I can do this.
I don't think it is possible to get that exact syntax, but if you want to do what Dictionary does, you need to define another type:
class PossibleSettingsDataList: IEnumerable<PossibleSettingsData> {
private List<PossibleSettingsData> list = new();
public void Add(int value, string definition, object meaning) {
list.Add(new() {
Value = value, Definition = definition, Meaning = meaning
});
}
public IEnumerator<PossibleSettingsData> GetEnumerator()
=> ((IEnumerable<PossibleSettingsData>)list).GetEnumerator()
IEnumerator IEnumerable.GetEnumerator()
=> ((IEnumerable)list).GetEnumerator();
}
The important thing here is the Add method and the conformance to IEnumerable<PossibleSettingsData>. This allows the 3 things you put in your nested {}s be passed to the Add method. For more info, see this.
Then you can do:
var PossibleSettings=new PossibleSettingsDataList
{
{ 5 ,"4800 baud", 4800},
{ 6 ,"9600 baud", 9600},
{ 7 ,"19200 baud" ,19200}
}.ToArray();
Adding a constructor:
public class PossibleSettingsData
{
public int Value { get; set; }
public string Definition { get; set; }
public object Meaning { get; set; }
public PossibleSettingsData()
{
}
public PossibleSettingsData(int value, string definition, object meaning)
{
Value = value;
Definition = definition;
Meaning = meaning;
}
}
We can write that:
var PossibleSettings = new PossibleSettingsData[]
{
new PossibleSettingsData(5 ,"4800 baud", 4800),
new PossibleSettingsData(6 ,"9600 baud", 9600),
new PossibleSettingsData(7 ,"19200 baud" ,19200)
};
But without the constructor:
var PossibleSettings = new PossibleSettingsData[]
{
new PossibleSettingsData { Value = 5, Definition = "4800 baud", Meaning = 4800},
new PossibleSettingsData { Value = 6, Definition = "9600 baud", Meaning = 9600},
new PossibleSettingsData { Value = 7, Definition = "19200 baud", Meaning = 19200}
};
Also with C# 9+ we can write, if I understood (I use C# 7.3):
var PossibleSettings = new PossibleSettingsData[]
{
new(5 ,"4800 baud", 4800),
new(6 ,"9600 baud", 9600),
new(7 ,"19200 baud" ,19200)
};
Of course we can create a specialized collection class as exposed by #Sweeper.

How can i add a property to object during the a run time at 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"
// }

List<T> with different values types

C#.
I have a class:
public class SQLValue<T>
{
public string nam { get; set; }
public string typ { get; set; }
public T val { get; set; }
}
now I want to create
List<SQLValue> lst = List<SQLValue>();
and add elements to it like that:
lst.Add(new List<SQLValue>(nam = "PlayerName", typ = "string", val = "Bot1"));
lst.Add(new List<SQLValue>(nam = "Ally", typ = "bool", val = true));
lst.Add(new List<SQLValue>(nam = "Levl", typ = "int", val = 2));
so I want to have a list of class that contain the value val with different types. Is it real?
You can't.
Some base type is required. Obviously, you can always use List<object>,
if you just want to store SQLValue<T> instances.
But, assuming, that you want to process list items depending on nam and typ properties, all you can do here is to extract some base class/interface:
public interface ISQLValue
{
public string nam { get; set; }
public string typ { get; set; }
public object val { get; set; }
}
implement it in SQLValue<T> this way:
public class SQLValue<T> : ISQLValue
{
public string nam { get; set; }
public string typ { get; set; }
public T val { get; set; }
object ISQLValue.val
{
get { return this.val; }
set { this.val = (T)value; }
}
}
and use List<ISQLValue> to store instances and process them:
var sqlValues = new List<ISQLValue>
{
new SQLValue<string> { nam="PlayerName", typ="string", val="Bot1" }
new SQLValue<bool> { nam="Ally", typ="bool", val=true }
new SQLValue<int> { nam="Levl", typ="int", val=2 }
};
foreach (var value in sqlValues)
{
Console.WriteLine($"nam = {value.name}, typ = {value.typ}, val = {value.val}");
}
That is, in case of some batch processing, ISQLValue will be used. But if you know T of particular ISQLValue, you can cast it to SQLValue<T> and use T val instead of object val.
No, you can't do that, because generics are eventually converted into separate types.
When a generic type is first constructed with a value type as a parameter, the runtime creates a specialized generic type with the supplied parameter or parameters substituted in the appropriate locations in the MSIL. Specialized generic types are created one time for each unique value type that is used as a parameter.
Reference: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generics-in-the-run-time
So SQLValue<int> and SQLValue<bool> are really two different types. As a result, you can't create a List<T> with,
var lst = new List<SQLValue>();
Instead, you have to specify the type T for SQLValue as well. So something like this would be allowed,
var lst = new List<SQLValue<bool>>();
Or,
var lst = new List<SQLValue<int>>();
Also, the syntax for adding elements to such a list is incorrect in your code. For example, if you are working with a list,
var lst = new List<SQLValue<bool>>();
You can add values to it using:
lst.Add(new SQLValue<bool> { nam="Ally", typ="bool", val=true });
Or, through the constructor, if you have defined one,
lst.Add(new SQLValue<bool> ("Ally", "bool", true ));
where the constructor could be:
public SQLValue(string nam, string typ, T val )
{
this.nam = nam;
this.typ = typ;
this.val = val;
}
You can create your own class, which will hold all that information:
class MyClass
{
public string Name { get; set; }
public Type PropType { get; set; }
public object Value { get; set; }
}
then you can add items into it:
List<MyClass> list = new List<MyClass>()
{
new MyClass(){ Name = "name1", PropType = typeof(string), Value = "asdasd" },
new MyClass(){ Name = "name2", PropType = typeof(bool), Value = true },
new MyClass(){ Name = "name3", PropType = typeof(int), Value = 11 },
};
and then use it for example like this:
foreach (var item in list)
{
switch (Type.GetTypeCode(item.PropType))
{
case TypeCode.String:
break;
case TypeCode.Int32:
break;
case TypeCode.Boolean:
break;
default:
throw new NotSupportedException();
}
}

is it possible to access properties by name, which is a variable?

Sorry if this is asked and answered, I searched but think I don't know the vocabulary to find the answer. Researched reflection but that doesn't seem to be the answer here? I'm a novice obviously. I'm trying/making minor contributions to a mod for the new Battletech game.
I've got this Dictionary and would like to use its keys to set properties as in the foreach below. I don't know if this is at compile or runtime, my guess is compile time...
I put *limb* in as pseudo-code for how I'm imagining it might work. The property mechDef.Head is an object of type LocationLoadoutDef with its property CurrentInternalStructure being float.
Hope that makes sense!
Much obliged for any assistance.
public class Settings {
public readonly Dictionary<string, bool> LimbRepair = new Dictionary<string, bool> {
{ "Head", false },
{ "LeftArm", false },
{ "RightArm", false },
{ "CenterTorso", false },
{ "LeftTorso", false },
{ "RightTorso", false },
{ "LeftLeg", false },
{ "RightLeg", false },
};
}
MechDef mechDef = new MechDef
(__instance.DataManager.MechDefs.Get(id), __instance.GenerateSimGameUID());
foreach (string limb in settings.LimbRepair.Keys) {
if (!settings.LimbRepair[limb]) {
mechDef.*limb*.CurrentInternalStructure = Math.Max
(1f, mechDef.*limb*.CurrentInternalStructure * (float)rng.NextDouble());
}
You can do it with Reflection, but....
This is quite easy to do with Reflection, and you'll probably get a couple answers on here that show you how, but since you are writing a game, I'm guessing you want the best performance possible, and Reflection isn't always going to give you that.
Below is a solution that requires no reflection but still allows you to use the loop structure you want. It just requires a little bit of setup when you create the object, then you can access your properties as if they were in a dictionary.
Solution: Use a dictionary of delegates to map the properties
First we need to write a utility class that represents a property. Since properties can be different types, this is a generic class with a type argument.
class PropertyWrapper<T>
{
private readonly Func<T> _getter;
private readonly Action<T> _setter;
public PropertyWrapper(Func<T> getter, Action<T> setter)
{
_getter = getter;
_setter = setter;
}
public T Value
{
get
{
return _getter();
}
set
{
_setter(value);
}
}
}
The idea behind this class is that you create it to represent any property you want, and call its methods to read and set the property. The class knows how to read and set the property because you tell it how, when you construct it, by passing it a short lambda expression that does the work.
This utility will allow you to put all the properties that represent limbs into a dictionary. Then you can look them up by string, just like your settings. So for example your MechDefinition might look like this:
class MechDef
{
public Limb Head { get; set; }
public Limb LeftArm { get; set; }
public Limb RightArm { get; set; }
public Limb LeftTorso { get; set; }
public Limb RightTorso { get; set; }
public Limb CenterTorso { get; set; }
public Limb RightLeg { get; set; }
public Limb LeftLeg { get; set; }
private readonly Dictionary<string, PropertyWrapper<Limb>> Properties;
public MechDef()
{
Properties = new Dictionary<string, PropertyWrapper<Limb>>
{
{"Head", new PropertyWrapper<Limb>( () => Head, v => Head = v ) },
{"LeftArm", new PropertyWrapper<Limb>( () => LeftArm, v => LeftArm = v ) },
{"RightArm", new PropertyWrapper<Limb>( () => RightArm, v => RightArm = v ) },
{"CenterTorso",new PropertyWrapper<Limb>( () => CenterTorso, v => CenterTorso = v )},
{"RightTorso", new PropertyWrapper<Limb>( () => RightTorso, v => RightTorso = v ) },
{"LeftTorso", new PropertyWrapper<Limb>( () => LeftTorso, v => LeftTorso = v ) },
{"RightLeg", new PropertyWrapper<Limb>( () => RightLeg, v => RightLeg = v ) },
{"LeftLeg", new PropertyWrapper<Limb>( () => LeftLeg, v => LeftLeg = v ) }
};
foreach (var property in Properties.Values) property.Value = new Limb();
}
public Limb this[string name]
{
get
{
return Properties[name].Value;
}
set
{
Properties[name].Value = value;
}
}
}
Yes, there is a bit of setup there, but it's all in one place, and it only executes once, when you instantiate the MechDef. Now you can access all of the limbs by string:
foreach (var pair in settings.LimbRepair)
{
if (pair.Value != false) continue;
var limb = mechDef[pair.Key];
limb.CurrentInternalStructure = Math.Max
(
1.0F,
limb.CurrentInternalStructure * (float)rng.NextDouble()
);
}
Link to DotNetFiddle example
You can create a DynamicObject to create your own dynamic Dictionary, See the explanation here
Assume that you want to provide alternative syntax for accessing
values in a dictionary, so that instead of writing
sampleDictionary["Text"] = "Sample text", you can write
sampleDictionary.Text = "Sample text".
This is the example from the same MSDN article above:
public class DynamicDictionary : DynamicObject
{
// The inner dictionary
Dictionary<string, object> dictionary = new Dictionary<string, object>();
public int Count
{
get { return dictionary.Count; }
}
// If you try to get a value of a property not defined
// in the class, this method is called.
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
// Converting the property name to lowercase so
// that property names become case-insensitive.
string name = binder.Name.ToLower();
// If the property name is found in a dictionary, set the result parameter
// to the property value and return true. Otherwise, return false.
return dictionary.TryGetValue(name, out result);
}
// If you try to set a value of a property that is not
// defined in the class, this method is called.
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// Converting the property name to lowercase so that
// property names become case-insensitive.
dictionary[binder.Name.ToLower()] = value;
// You can always add a value to a dictionary, so this method always returns true.
return true;
}
}
And this is how you can use your DynamicDictionary:
dynamic person = new DynamicDictionary();
// Adding new dynamic properties. The TrySetMember method is called.
person.FirstName = "Ellen";
person.LastName = "Adams";
Reflection is one way to get at it. https://stackoverflow.com/a/1954663/83250 actually answers this perfectly. I would however restructure your data so the mechDef object is another dictionary but if you must keep it like your question asks, this will work:
void Main()
{
Dictionary<string, bool> limbRepair = new Dictionary<string, bool>
{
{ "Head", false },
{ "LeftArm", false },
{ "RightArm", false },
// Etc.
};
MechDefinition mechDef = new MechDefinition();
List<Limb> limbs = new List<Limb>();
foreach (KeyValuePair<string, bool> limbsToRepair in limbRepair.Where(x => !x.Value))
{
Limb limb = mechDef.GetPropValue<Limb>(limbsToRepair.Key);
limb.CurrentInternalStructure = 9001;
}
}
public class MechDefinition
{
public MechDefinition()
{
Head = new Limb
{
Id = Guid.NewGuid(),
DateAdded = DateTime.Parse("2018-01-01"),
Name = "Main Head",
CurrentInternalStructure = 8675309
};
}
public Guid Id { get; set; }
public string Name { get; set; }
public int CurrentInternalStructure { get; set; }
public Limb Head { get; set; } = new Limb();
public Limb LeftArm { get; set; } = new Limb();
public Limb RightArm { get; set; } = new Limb();
// etc...
}
public class Limb
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTime DateAdded { get; set; }
public int CurrentInternalStructure { get; set; }
public bool IsDisabled { get; set; }
}
public static class ReflectionHelpers
{
public static object GetPropValue(this object obj, string name)
{
foreach (string part in name.Split('.'))
{
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
public static T GetPropValue<T>(this object obj, string name)
{
object retval = GetPropValue(obj, name);
if (retval == null) { return default(T); }
// throws InvalidCastException if types are incompatible
return (T)retval;
}
}
Be aware that reflection is a very costly operation. If you are dealing with large sets of data, it will be very inefficient. Take a look at https://stackoverflow.com/a/7478557/83250 for a performance overview.
Also code-wise, I prefer to stay away from dynamic and reflection altogether. Reflection has its perks when you need to access a property attribute and dynamic is great if you don't have a strongly typed object. With that said, C# is a strongly typed language and should be treated as such whenever possible. By restructuring your mechDef as a Dictionary<string, Limb> object or something similar you will have a more efficient application.
If I understand correctly, You have something like this:
class LocationLoadoutDef
{
public LocationLoadoutDef()
{
Head = new Prop();
LeftArm = new Prop();
RightArm = new Prop();
CenterTorso = new Prop();
LeftTorso = new Prop();
RightTorso = new Prop();
LeftLeg = new Prop();
RightLeg = new Prop();
}
public Prop Head { get; set; }
public Prop LeftArm { get; set; }
public Prop RightArm { get; set; }
public Prop CenterTorso { get; set; }
public Prop LeftTorso { get; set; }
public Prop RightTorso { get; set; }
public Prop LeftLeg { get; set; }
public Prop RightLeg { get; set; }
...
}
class Prop
{
public float CurrentInternalStructure { get; set; }
...
}
So you can use reflection getting the type of the object and the property.
This is an example based on your pseudocode:
// your instance of LocationLoadoutDef
var mechDef = new LocationLoadoutDef();
//For reflection you need obtain the type
Type mechType = mechDef.GetType();
// loop your Dictionary
foreach (string limb in LimbRepair.Keys)
{
// If the property is false in the dictionary and the type has a property with that name
if (!LimbRepair[limb] && mechType.GetProperties().Any(p => p.Name == limb))
{
// Obtain the instance of the property
var property = mechType.GetProperty(limb).GetValue(mechDef) ;
// Get the property type
Type propertyType = property.GetType();
// If the property has a property CurrentInternalStructure
if (propertyType.GetProperties().Any(p => p.Name == "CurrentInternalStructure"))
{
// Obtain the current value for CurrentInternalStructure
var currentValue = propertyType.GetProperty("CurrentInternalStructure").GetValue(property);
// calculate the new value (I don't know what is rng)
var newValue = 1f ; //Math.Max(1f, (float)currentValue * (float)rng.NextDouble());
// set de value in the property
propertyType.GetProperty("CurrentInternalStructure").SetValue(property, newValue);
}
}
}
You can always create classic and working if .. else or switch.
Or create dictionary with function to update correct property
public class Repair
{
public bool Active { get; set; }
public Action<MechDef> Update { get; set; }
}
public class Settings
{
public readonly Dictionary<string, Repair> LimbRepair =
new Dictionary<string, bool> {
{
"Head",
new Repair { Active = false, mechDef => mechDef.Head.CurrentInternalStructure = yourFunctionForHead }
},
{
"LeftArm",
new Repair { Active = false, mechDef => mechDef.LeftArm.CurrentInternalStructure = yourFunctionForLeftArm }
},
// ... and so on
};
}
Then in the loop you will call correct update action, become much cleaner to use settings class with benefits of strong types and compiler help which prevent dynamic runtime errors
var updates = settings.LimbRepair.Where(pair => pair.Value.Active == false)
.Select(pair => pair.Value);
foreach (var repair in updates)
{
repair.Update();
}

Adding values using LINQ to an object property with a Dictionary property

I have a dataset which returns a couple of contact information in string(Phone, mobile, skype). I created an object with a Dictionary property where i can put the contact information in a key value pair. The problem is, I am assigning the values of the object using Linq. Hope somebody can help. Here is my code:
public class Student
{
public Student()
{
MotherContacts = new ContactDetail();
FatherContacts = new ContactDetail();
}
public ContactDetail MotherContacts { get; set; }
public ContactDetail FatherContacts { get; set; }
}
public class ContactDetail
{
public ContactDetail()
{
Items = new Dictionary<ContactDetailType, string>();
}
public IDictionary<ContactDetailType, string> Items { get; set; }
public void Add(ContactDetailType type, string value)
{
if(!string.IsNullOrEmpty(value))
{
Items.Add(type, value);
}
}
}
public enum ContactDetailType
{
PHONE,
MOBILE
}
Here's how I assign value to the Student object:
var result = ds.Tables[0].AsEnumerable();
var insuranceCard = result.Select(row => new Student()
{
MotherContacts.Items.Add(ContactDetailType.PHONE, row.Field<string>("MotherPhone"),
MotherContacts.Items.Add(ContactDetailType.MOBILE, row.Field<string>("MotherMobile")
}).FirstOrDefault();
The compiler says that the MotherContacts is not recognized in the context. What should I do?
I think your code should look like:
var insuranceCard = result.Select(row =>
{
var s = new Student();
s.MotherContacts.Items.Add(ContactDetailType.PHONE, row.Field<string>("MotherPhone");
s.MotherContacts.Items.Add(ContactDetailType.MOBILE, row.Field<string>("MotherMobile");
return s;
}).FirstOrDefault();
You are using the object initializer syntax in a wrong way. The correct use is:
new Student{MotherContacts = value} where value must be a ContactDetail.

Categories