In JavaScript, I can call a function like so:
x = myFunction({"meetingID": 2, "meetingRoom": "A103"});
myFunction() then receives an object which I can parse with JSON, or just by referencing the object's properties:
function myFunction( args ) {
var x = args.meetingID;
}
Is there any such similar construct in C#? Are there such things as "inline objects", or "on the fly objects"?
You can use anonymous type in conjunction with dynamic keyword.
void MyFunction(dynamic args)
{
var x = args.MeetingId;
}
MyFunction(new { MeetingId = 2, MeetingRoom = "A103" });
Beware - this works different from javascript. If object passed to MyFunction doesn't contain property MeetingId, you'll get exception at runtime.
You could use a dictionary
public static void Main()
{
myFunction(new Dictionary<string, object>()
{
{ "meetingID", 2},
{ "meetingRoom", "A103"}
}
);
}
public static void myFunction(Dictionary<string,object> args)
{
var x = args["meetingID"];
}
Just a small suggestion .. if possible, it will be safer to use optional parameters instead:
string myFunction( int meetingID = 0, string meetingRoom = null ) {
var x = meetingID;
}
then you can use it like :
var x = myFunction( meetingID: 2, meetingRoom: "A103" );
var y = myFunction( meetingRoom:"A103" ); // order doesn't matter if you specify the parameter name
var z = myFunction( 3, "B109" );
var _ = myFunction();
Related
I understand that you can configure C# enum flags in this way:
[Flags]
public enum MyEnum
{
Unknown = 0,
Type1 = 1,
Type2 = 2,
Type3 = 4,
Type4 = 8,
Type5 = 16
}
And once this is configured, you can represent a set of enumberations like so:
MyEnum enumerationSet = MyEnum.Type1 | MyEnum.Type2
Then you can make checks against this set, such as:
if(enumerationSet.HasFlag(MyEnum.Type1))
{
// Do something
}
Or print their values, like so:
Console.WriteLine("{0}", enumerationSet);
Which would print:
Type1, Type2
However, can I go in reverse order? For instance, if I know that
MyEnum.Type1 | MyEnum.Type2 == 3
Can I then ask MyEnum what set of its value/types would equal 3? Then, I can create an extension method (GetSet) to execute like this:
List<MyEnum> myEnumSetList = MyEnum.GetSet(3)
Returning either a MyEnum set or a set of values, i.e. {1, 2}.
Please advise.
EDIT: I was able to finally figure it out. Posted my answer below.
You can parse it manually with this code:
var res = 3;
var myEnumSetList = res.ToString()
.Split(new[] { ", " }, StringSplitOptions.None)
.Select(v => (MyEnum)Enum.Parse(typeof(MyEnum), v)).ToList();
If you want a list of flags you can use this:
var f = 1 + 4 + 8;
var s = Convert.ToString(f, 2);
var flags =
s.Where(w=> w !='0').Select(
(c, i) =>
(MyEnum)Enum.Parse(typeof(MyEnum),
(int.Parse(c.ToString())*Math.Pow(2, i)).ToString(CultureInfo.InvariantCulture)));
You can just cast the Integer to an Enum and use an & comparison.
example
var num = 1;
var doesExist = (((enumerationSet) & ((MyEnum) num)) != 0);
Then if it exists you can return it in your extension method.
Full Code
var enumList = new List<MyEnum>();
var testNumbers = new List<int>{ 1, 2, 4};
MyEnum enumerationSet = MyEnum.Type1 | MyEnum.Type2;
foreach (var num in testNumbers)
{
var doesExist = (((enumerationSet) & ((MyEnum) num)) != 0);
if (doesExist)
enumList.Add((MyEnum)num);
}
enumList.ForEach(x => Console.WriteLine(x.ToString()));
return enumList;
After some hacking around, I was able to resolve a list of enum values, based on the value of that respective set OR'ed:
protected List<MyEnum> GetEnumSet(int flagNumber)
{
List<MyEnum> resultList= new List<MyEnum>();
foreach (MyEnum value in Enum.GetValues(typeof(MyEnum)))
{
if (((MyEnum)flagNumber).HasFlag(value))
{
resultList.Add(value);
}
}
return resultList;
}
Here, flagNumber is the value of a respective list OR'ed, i.e. MyEnum.Type1 | MyEnum.Type2. Thus, by sending this method the flagNumber, I get the list { MyEnum.Type1, MyEnum.Type2 }
I have a string "hello", and a integer 1.
I want to convert them into
new { hello= 1 }
dynamically, and without using any condition like
switch(p1){
case "hello":
return new {hello=p2};
}
as there is many different string and I need to put many items into a super object set like
var emotion = {smile=1,angry=2,worry=3}
the problem is smile, angry and worry was string. but after added to emotion, they are not string, but just an index (like dictionary, however dictionary's index also has dataType, which is not my expected result)
Is it possible?
--- Updated --- i have added a function to specify the expected output.
private void Question_1()
{
//i have
string a = "hello";
int b = 1;
// i want to convert a and b to new {a = b} programmatically, for example i can convert a and b to a Tuple like
Tuple<string, int> x = new Tuple<string, int>(a,b);
//but i dont know how to to convert it to new {a = b}, as i need to put the string "hello" as key to new {a=b}
var result = new { hello = b }; //you can see i can put b after =, but i can never put the string hello at the left
}
private void Question_2()
{
//and the final should be like this
List<Tuple<string, int>> list = new List<Tuple<string, int>>() {
new Tuple<string,int>("smile",1),
new Tuple<string,int>("cry",2),
new Tuple<string,int>("worry",3)
};
foreach (Tuple<string, int> item in list)
{
//adding item's string and int into result and finally the result is
}
//the final result
var finalResult = new { smile = 1, cry = 2, worry = 3 };
}
Use .NET naming conventions for enums: They should be Pascal Notation.
enum Emotion
{
Smile = 1, Angry = 2, Worry = 3
}
var l = new List<Emotion> { Emotion.Angry, Emotion.Smile, Emotion.Worry };
You can also use a friendly name for your enum with the DesriptionAttribute like this:
enum Emotion
{
[Description("Smiling")]
Smile = 1,
[Description("Angry Type")]
Angry = 2,
[Description("Worry Type")]
Worry = 3
}
Any reason you can't just use a dictionary?
var hi = new Dictionary<string,int>();
hi[p1] = p2;
return hi; // Would serialize the same way as your anonymous object
If not, then you could use the expando object to dynamically set properties at runtime.
var hi = new ExpandoObject() as IDictionary<string, object>;
hi.Add(p1, p2);
var p2Value = (int)((dynamic)hi).hello;
You can use ExpandoObject.
class Program
{
static dynamic obj = new ExpandoObject();
static void Main(string[] args)
{
AddProperty("City", "Sydney");
AddProperty("Country", "Australia");
AddProperty("hello", 1);
Console.WriteLine(obj.City);
Console.WriteLine(obj.Country);
Console.WriteLine(obj.hello);
//We can even use dynamic property names ( e.g. cityProp in below example )
IDictionary<string, object> dic = obj as IDictionary<string, object>;
Console.WriteLine("City is : " + dic[cityProp]);
}
public static void AddProperty(string propertyName, object value)
{
IDictionary<string, object> a = obj as IDictionary<string, object>;
a[propertyName] = value;
}
}
dynamic emotion = new { smile = 1, angry = 2, worry = 3 };
Console.WriteLine(emotion.smile);
Like this?
Edit: Based on your comment on another answer:
it is not worked, i need it able to be accepted by
Url.Action("action","controller", x), where x is thing that i'm trying
to create dynamically . i don't know if dynamic too complex or what.
but Url.Action dont know how to read it
There's obviously more to the question than just C#, clearly this an MVC question. You should really add as much information as you can about what you need.
Your answer is probably here:
https://stackoverflow.com/a/15112223/1685167
The #Url.Action() method is proccess on the server side, so you cannot
pass a client side value to this function as a parameter.
Would it be possible to create code like this:
private static string GetInsertString<TDto>()
{
var type = typeof(TDto);
var properties = type.GetProperties().Where(Where);
var tableName = type.Name;
return string.Format("INSERT INTO {0} ({1}) VALUES ({2});",
tableName,
string.Join(",", properties.Select(x => x.Name).ToArray()),
string.Join(",", properties.Select(x => string.Format("#{0}", x.Name.ToLower())).ToArray()));
}
that works with anonymous types like this:
var point = new { X = 13, Y = 7 };
PS:
Output would be:
INSERT INTO Anonymous (X, Y) values (13, 7)
of course you may want to provide the table name.
You won't be able to specify the type parameter with an anonymous type, but if you pass it an object as a parameter, you can use type inference to get a hold of the type:
private static string GetInsertString<TDto>(TDto dto)
{
var type = typeof(TDto);
var propertyNames = type.GetProperties().Where(Where).Select(x => x.Name);
return string.Format("INSERT INTO {0} ({1}) VALUES ({2});",
type.Name,
string.Join(",", propertyNames),
string.Join(",", propertyNames.Select(x => string.Format("#{0}", x.ToLower())));
}
Then call the method: var insertString = GetInsertString(new { X = 13, Y = 7 });
It is very hard to use anonymous types with a ...<T>() method. The main way of doing that involves the by example hack, i.e.
var dummy = new { X = 13, Y = 7 };
Foo(dummy); // for Foo<T>(T obj)
or more succinctly:
Foo(new { X = 13, Y = 7 });
which uses generic type inference to deduce that T here is the anonymous type. Foo<T>(T obj) could either be your actual method, or could be a method that in turn calls GetInsertString<TDto>(), i.e.
// overload that takes an example object as a parameter
private static string GetInsertString<TDto>(TDto example) {
return GetInsertString<TDto>();
}
You could also probably combine the two:
private static string GetInsertString<TDto>(TDto example = null) {
.. your code ..
}
and pass the example only when it is necessary.
However, the "by example" approach is brittle and susceptible to breaking. I strongly recommend that you simply define a POCO instead:
public class MyType {
public int X {get;set;}
public int Y {get;set;}
}
and use GetInsertString<MyType>.
Assuming you're using .net 4.0 or above, you can use dynamic and ExpandoObject like this:
private static string GetInsertString(dynamic obj)
{
var expando = (ExpandoObject)obj;
return string.Format("INSERT INTO {0} ({1}) VALUES ({2});",
"tableName",
string.Join(",", expando.Select(x => x.Key)),
string.Join(",", expando.Select(x => x.Value is string ? "'" + x.Value + "'" : x.Value.ToString())));
}
And then:
dynamic o = new ExpandoObject();
o.a = 10;
o.b = "hello";
var s = GetInsertString(o);
Now s is INSERT INTO tableName (a,b) VALUES (10,'hello');.
This is only a draft you have to do some work to get a correct insert string.
You can use anonymous objects with generic methods as long as the compiler can resolve the type. For instance, if it can be resolved from a parameter. Like this:
private static string GetInsertString<TDto>(TDto someObject) {
var type = typeof(TDto);
var properties = type.GetProperties(); // Removed .Where(Where) since it didn't compile
var tableName = type.Name;
return string.Format(
"INSERT INTO {0} ({1}) VALUES ({2});",
tableName,
string.Join(",", properties.Select(x => x.Name).ToArray()),
string.Join(",", properties.Select(x => string.Format("#{0}", x.Name.ToLower())).ToArray())
);
}
var point = new { X = 13, Y = 7 };
var insertSql = Test.GetInsertString(point);
// Results in: INSERT INTO <>f__AnonymousType0`2 (X,Y) VALUES (#x,#y);
I have this code :
(simple enum which has values for a,b,c ...[0,1,2] , and i want to show for each looped number - its corrosponding enum in a final list).
public enum ENM
{
a,b,c
}
void Main()
{
var e = Enumerable.Range(0,3).Select(myCounter=>new {
final=((Func<int,ENM>)delegate (int i)
{
return (ENM)i;
})(myCounter)
}).ToList();
this is fine and working.
Is there any solution without writing delegate(int i) {...}?
p.s. of course I can just write (ENM)i but the question is for learning
how to write ( in different ways ) the auto-executed methods.
Why not
Enumerable.Range(0,3).Select(c=>(ENM)c).ToList()
or am I missing some reason for the over complexity?
var e = Enumerable.Range(0, 3).Select(myCounter => new
{
final = ((Func<int, ENM>)(
i=>{
return (ENM)i;
/* More code could be here */
}))(myCounter)
}).ToList();
is about as tight as you will get if you want the same mess :)
var e = Enum.GetNames(typeof(ENM)).Select((e, i) => new { final = e, index = i }).ToList();
OR
var EnumNames = Enum.GetNames(typeof(ENM));
var EnumValues = Enum.GetValues(typeof(ENM)).Cast<ENM>().Select(e => (int)e);
var result = EnumNames.Zip(EnumValues, (n, v) => new { final = n, index = v });
There's a specific method in System.Enum for doing exactly this:
var arr = Enum.GetValues(typeof(ENM));
To get it into a List<ENM>:
var lst = arr.Cast<ENM>().ToList();
I've got a JArray that represents the json substring [1,2,3]. I'd like to turn it into an int[] instead.
What's the correct way of doing this? The best way I've found so far is to do the following:
int[] items = new int[myJArray.Count];
int i = 0;
foreach (int item in myJArray)
{
items[i++] = item;
}
myJArray.ToObject<int[]>();
You can also specify HashSet, List etc.
The accepted answer relies on .NET's conversion - this technique uses JSON.NET's own in addition to what .NET can provide so works with more scenarios.
It's also faster as it isn't using a generator & closure for the LINQ operation.
int[] items = myJArray.Select(jv => (int)jv).ToArray();
A cast needed first for me:
((Newtonsoft.Json.Linq.JArray)myJArray).Select(item => (int)item).ToArray()
This is pretty weak because you have to convert back into a string, but if you are doing something quick and dirty, where the performance hit won't matter, I use the below method. I like it because I don't have to write any code to map properties between json/JObject and my POCO's.
public static class JsonExtensions {
public static T As<T>(this JObject jobj) {
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(jobj));
}
public static List<T> ToList<T>(this JArray jarray) {
return JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(jarray));
}
}
[Test]
public void TestDeserializeRootObject() {
var json = #"{ id: 1, name: ""Dwight"" }";
var jfoo = JsonConvert.DeserializeObject(json);
var foo = (jfoo as JObject).As<Foo>();
Assert.AreEqual(1, foo.Id);
Assert.AreEqual("Dwight", foo.Name);
}
[Test]
public void TestDeserializeArray() {
var json = #"[
{ id: 1, name: ""Dwight"" }
, { id: 2, name: ""Pam"" }
]";
var foosArr = JsonConvert.DeserializeObject(json);
Assert.IsInstanceOf<JArray>(foosArr);
Assert.AreEqual(2, (foosArr as JArray).Count);
var foos = (foosArr as JArray).ToList<Foo>();
Assert.AreEqual(2, foos.Count);
var foosDict = foos.ToDictionary(f => f.Name, f => f);
Assert.IsTrue(foosDict.ContainsKey("Dwight"));
var dwight = foosDict["Dwight"];
Assert.AreEqual(1, dwight.Id);
Assert.AreEqual("Dwight", dwight.Name);
Assert.IsTrue(foosDict.ContainsKey("Pam"));
var pam = foosDict["Pam"];
Assert.AreEqual(2, pam.Id);
Assert.AreEqual("Pam", pam.Name);
}
int[] items = new int[myJArray.Count];
for (int i=0; i < myJArray.Count;i++)
{
items[i] = (int)myJArray[i]
}
this is the fastes solution you can do. The classic for is a bit faster than the ForEach as you access the item by the index(the foreach behind the scene uses the IEnumerator interface)
or if you prefer:
JsonArray arr = JsonConvert.Import("[1,2,3,4]");
int[] nums = (int[]) arr.ToArray(typeof(int));