I have a dbf file (dBase) that I want to read, put each row into a single list (since a row represents data about one shapefile object), and then be able to modify the list (e.g., convert fields which represent the name to a string). This means that the datatype need to be able to hold both Ints, strings, bool and so on, and add items to, it. In python I could do this with lists, but since sets cant be modified, I cant use them.
This sounds like a (exact) duplicate to Alternative to Tuples,
but it isn't. These questions are based on the assumption that you know which objects you want beforehand; I don't.
I'm on .NET 4.5, btw.
Use dynamic - it is a perfect use case for it:
Visual C# 2010 introduces a new type, dynamic. The type is a static type, but an object of type dynamic bypasses static type checking. In most cases, it functions like it has type object. At compile time, an element that is typed as dynamic is assumed to support any operation. Therefore, you do not have to be concerned about whether the object gets its value from a COM API, from a dynamic language such as IronPython, from the HTML Document Object Model (DOM), from reflection, or from somewhere else in the program. However, if the code is not valid, errors are caught at run time.
If you want to be able to easily add properties at runtime and change their types, you can use ExpandoObject with dynamic, for example:
dynamic expando = new ExpandoObject();
expando.SomeProperty = "1234";
Console.WriteLine(expando.SomeProperty);
Console.WriteLine(expando.SomeProperty.GetType().FullName); // string
expando.SomeProperty = int.Parse(expando.SomeProperty);
Console.WriteLine(expando.SomeProperty);
Console.WriteLine(expando.SomeProperty.GetType().FullName); // int
Have you tried using the dynamic type?
Related
Im trying to write a small framework for REST-API testing. Im using a lot of reflection and came to a problem I cant help myself.
Im using this line to extract a variable the user gives my as a path (string)
object o = input.GetType().GetProperty(name).propertyInfo.GetValue(input, null);
This object can be a normal type T or a List<T>.
Now if its a List and I know the type everything is simple, I can use
List<string> l = (List<string>)o; // I know its a List<string> because the user told me
To parse the object into the given array. But I dont always know the type of the objects in the list and
List<object> l = (List<object>)o; // I dont know the type and I dont care
gives me an error.
Object of type "System.Collection.GenericList[System.String]" can not
be converted to "System.Collection.GenericList[System.Object]"
Is there anything I can do to receive the list of objects? I dont want the user to specify the type because its only the last variable I want to care about. Like
The user wants to test "object1.a.b.c" I only need to know the type of c, because thats where the test runs.
TIA
You may convert it to IEnumerable<object>, but not List<object>. The reason is: a list of bananas is not a list of fruit because you can put an apple into a list of fruit, but not into a list of bananas. Since the two types allow different operations, they are not compatible.
A sequence has no "put into" operation, so it is possible to use a list of bananas as a sequence of fruit. Similarly, you can use a list of strings as a sequence of objects, but not a list of objects.
This feature is called generic covariance; for more information, do a search on C# covariance and you'll find plenty of articles explaining how it works.
Note in particular that covariance only works on reference types; you may not use a sequence of integers as a sequence of objects. Do you see why?
Alternatively, if you have an IEnumerable in hand, you can make a copy of any sequence into a list of objects with mysequence.Cast<object>().ToList(). But this is a copy, not a reference conversion.
Since your problem begins at processing dynamic objects that arrive as JSON to the server, it's quite convenient to use the JSON Processing library itself to test for certain characteristics before converting to POCOs. Using newtonsoft's JSON.Net,
var o = JObject.Parse(json);
JToken property = o["a"]["b"]["c"];
if (property != null)
{
if (property.Type == JTokenType.Array)
{
// Process property as array
}
else if (property.Type == JTokenType.Object)
{
// Process property as object
}
// Magnitude of other types
}
I do understand the need to convert to .NET types before final processing but I would highly recommend beginning with JObjects as the library is designed for this purpose and provides numerous convenience methods for many dynamic operations that C# doesn't provide natively.
JToken Type Reference
JObject Class
I have a anonymous class:
var someAnonymousClass = new
{
SomeInt = 25,
SomeString = "Hello anonymous Classes!",
SomeDate = DateTime.Now
};
Is there anyway to attach Attributes to this class? Reflection, other? I was really hoping for something like this:
var someAnonymousClass = new
{
[MyAttribute()]
SomeInt = 25,
SomeString = "Hello anonymous Classes!",
SomeDate = DateTime.Now
};
You're actually creating what is called an anonymous type here, not a dynamic one.
Unfortunately no there is no way to achieve what you are trying to do. Anonymous types are meant to be a very simple immutable type consisting of name / value pairs.
The C# version of anonymous type only allows you to customize the set of name / value pairs on the underlying type. Nothing else. VB.Net allows slightly more customization in that the pairs can be mutable or immutable. Neither allow you to augment the type with attributes though.
If you want to add attributes you'll need to create a full type.
EDIT OP asked if the attributes could be added via reflection.
No this cannot be done. Reflection is a way of inspecting metadata not mutating it. Hence it cannot be used to add attributes.
Additionally, type definitions in an assembly, and in general, are immutable and cannot be mutated at runtime [1]. This includes the adding of attributes to a method. So other reflection like technologies cannot be used here either.
[1] The one exception to this is ENC operation
First of all, this is an anonymous type. The word "dynamic" might lead people to think you're talking about a C# 4.0 class implementing dynamic semantics, which you aren't.
Secondly, no, you're not able to do what you ask.
If you need to specify attributes for your properties, you're back to a named type, ie. a normal class or struct.
It is possible to add attributes to an anonymous instance using TypeDescriptor.AddAttributes. You can then later access the attributes using TypeDescriptor.GetAttributes.
This will not add them to the Type instance for the object. So it may not be useful in your case if you do not control the code that retrieves and applies the attributes.
I have an AnonymousType object that contacts two fields with their values. How can I access the value of these fields?
Ex:
SourceTypeObject { Source_Type_Id = 1, Source_Type_Name = "bibliography" }
I need to do something like : SourceTypeObject.Source_Type_Id
Is that possible?
EDIT:
Here's what I get if I tried to access the property directly:
Yes, this is the exact purpose of anonymous types. The only thing that might prevent you from doing so is if you passed the anonymous type around as a parameter with type "object". This would hide information about the anonymous type, and it would look like just any old object then.
The only recourse if this is the case is to use reflection, which is slow and awkward. Anonymous types are a meant to be a very "local" phenomenon, and if you find yourself wanting to use them elsewhere in the program, it's worth the time to promote it to a real type.
EDIT: In response to the image you posted, assuming the array is declared locally just outside of view, try to replace the object SourceTypeObject with var SourceTypeObject. This allows it to infer the anonymous type instead of being told that it's an object.
I need to loop over a List<dynamic> objects.
The list's objects all have values, but for some reason, I am not able to access any of the dynamic object fields. Below is a screenshot of my debug window:
There you can see the object contains fields (such Alias, Id, Name, etc).
I tried both casting it to a IDictionary<string, object> and ExpandoObject, to no avail. I did not face such a thing before: failing to access existing fields in a dynamic object when they exist.
What is wrong here?
The code is throwing a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException with a message stating {"'object' does not contain a definition for 'Name'"}.
The list was created adding anonymously-typed objects, like this:
return new List<dynamic>(fields.Select(field => new
{
Id = field.Id,
Alias = field.Alias,
Name = field.Name,
Type = field.Type,
Value = field.Value,
SortOrder = field.SortOrder
}));
where fields is an ICollection<Field>, a strongly-typed collection.
The telling part is the exception:
{"'object' does not contain a definition for 'Name'"}.
This indicates that the runtime binder was not actually capable of accessing the type you're passing in dynamic (since dynamic does actually enforce visibility rules).
The most likely cause of this is that you're creating the anonymous type in a different assembly from the one where you're subsequently reading it - since anonymous types are declared internal, the consuming assembly cannot access it, causing the error message above.
Contrast with the usual case of runtime binder exceptions:
'<>f__AnonymousType0< string >' does not contain a definition for 'Name'
EDIT:
A possible solution to the problem is to use the InternalsVisibleToAttribute on the assembly containing the anonymous type. However, this is code smell - just like any other use of InternalsVisibleToAttribute or internal itself.
A better way would be to make sure you don't actually pass anonymous types over assembly boundaries - after all, they shouldn't even be used outside of the method they originated from; the fact that they are is basically an implementation detail of .NET - they didn't have another way to do the same thing. This could change in future versions, making the InternalsVisibleToAttribute solution doubly unreliable.
The way your code is using dynamic suggests that your team has flawed assumptions about how dynamic works and how it's supposed to be used. Note how the actual runtime type of List<dynamic> is actually List<object>. The same goes for arguments of type dynamic (which are again just object, albeit marked with DynamicAttribute). And in fact, that really is what dynamic is - it's a way to handle runtime dynamic dispatch - it's not a property of the type or anything, it's just the way you actually invoke whatever you're trying to invoke. For C#, dynamic allows you to skip most of the compiler checks when working with those dynamic types, and it generates some code to handle the dispatch for you automatically, but all of that only happens inside the method where you actually use the dynamic keyword - if you used List<object>, the end result would be exactly the same.
In your code, there's no reason not to use simple static types. Dynamic typing doesn't really give you any benefits, apart from the effort to code the types themselves. If your co-workers don't like that, well, they should present a better solution - the problem is quite obvious, and it's something you need to deal with.
Much worse, it explicitly hides all context, all the type information. That's not something you want in an API, internal or not! If you want to hide the concrete types being used, why not - but you should still expose an interface instead. I suspect this is the reason why anonymous types can't implement interfaces - it would encourage you to go entirely the wrong way.
In C#, I would like to figure out if it's possible to declare an anonymous type where the fields are not known until run-time.
For example, if I have a List of key/value pairs, can I declare an anonymous type based on the contents of that list? The specific case I'm working with is passing parameters to Dapper, where I don't know ahead of time how many parameters I will have.
List<Tuple<string, string>> paramList = new List<Tuple<string, string>>() {
new Tuple<string, string>("key1", "value1"),
new Tuple<string, string>("key2", "value2")
...
};
I'd like to convert this List (or an equivalent Map) into an anonymous type that I can pass to Dapper as query parameters. So ideally, the above list would wind up looking like this, if defined as an anonymous type:
new { key1=value1, key2=value2, ... }
I've seen several questions on StackOverflow asking about extending anonymous types after they are declared ("extendo objects"), or declaring arbitrary fields on an object after it's created, but I don't need to do that... I just need to declare the types dynamically up-front once. My suspicion is that it will require some fancy reflection, if it's possible at all.
My understanding is that the compiler defines a type for anonymous classes under the hood at compile-time, so if the fields of that class are not available until run-time, I might be out of luck. My use case may in fact be no different in actuality than using an "extendo object" to define arbitrary fields, whenever.
Alternatively, if anyone knows of a better way to pass query parameters to Dapper (rather than declaring an anonymous class), I would love to hear about that as well.
Thanks!
UPDATE
Sorry for the delay in getting back to this one! These answers were all great, I wish I could give points to everyone. I ended up using jbtule's solution (with edit by Sam Saffron), passing IDynamicParameters to Dapper, so I felt I had to give the answer to him. The other answers were also good, and answered specific questions that I had asked. I really appreciate everyone's time on this!
Dapper's creators were very aware of this problem. This kind of functionality is really needed for INSERT and UPDATE helpers.
The Query, Execute and QueryMultiple methods take in a dynamic parameter. This can either be an anonymous type, a concrete type or an object that implements IDynamicParameters.
public interface IDynamicParameters
{
void AddParameters(IDbCommand command, Identity identity);
}
This interface is very handy, AddParameters is called just before running any SQL. Not only does this give you rich control over the parameters sent to SQL. It allows you to hook up DB specific DbParameters, since you have access to the command (you can cast it to the db specific one). This allows for support of Table Values Parameters and so on.
Dapper contains an implementation of this interface that can be used for your purposes called DynamicParameters. This allows you to both concatenated anonymous parameter bags and add specific values.
You can use the method AddDynamicParams to append an anonymous type.
var p = new DynamicParameters();
p.AddDynamicParams(new{a = "1"});
p.AddDynamicParams(new{b = "2", c = "3"});
p.Add("d", "4")
var r = cnn.Query("select #a a, #b b, #c c, #d d", p);
// r.a == 1, r.b == 2, r.c == 3, r.d == 4
In C#, I would like to figure out if it's possible to declare an anonymous type where the fields are not known until run-time.
Anonymous types are generated by the compiler. You want to know if the compiler will generate you a compiler-generated type with field types not known to the compiler. Clearly it cannot do so; as you correctly surmise, you are out of luck.
I've seen several questions on StackOverflow asking about extending anonymous types after they are declared ("extendo objects")
We usually call those "expando" objects.
If what you want to do is make an expando object based on a dictionary of key-value pairs, then use the ExpandoObject class to do that. See this MSDN article for details:
http://msdn.microsoft.com/en-us/magazine/ff796227.aspx
If what you want to do is generate a bona-fide .NET class at runtime, you can do that too. As you correctly note, you need some fancy reflection to do so. What you want to do is make a collectible assembly (so-called because unlike a normal assembly, you generate it at runtime and the garbage collector will clean it up when you are done with it.)
See http://msdn.microsoft.com/en-us/library/dd554932.aspx for details on how to make a collectible assembly and emit a type into it using a TypeBuilder.
You can't use an anonymous type. Anonymous types are generated by the compiler rather than at run-time. You could certainly use dynamic though:
dynamic dynamicObj = new ExpandoObject();
var objAsDict = (IDictionary<String, Object>)dynamicObj;
foreach(var item in paramList)
{
objAsDict.Add(item.Item1, item.Item2);
}
You can then use dynamicObj as a regular object:
Console.WriteLine(dynamicObj.key1); // would output "value1"