Casting a C# List<> - reflection

I have what seems to be a simple problem but one that I can't seem to find answers to. I have a class with properties. One of those properties returns a List. I have a method that cycles through all properties of any kind of class and produces a TreeNode for that class (a communication log application). When I come across the property identified as a List, I don't know how to cast the property.GetValue properly. the property.PropertyType is known but what ever I try, I get a compilation error or a runtime error.
Here is what I'm trying to do...
foreach (PropertyInfo prop in props)
{
if(prop.PropertyType.Namespace == "System.Collections.Generic")
{
List<object> oList = prop.GetValue(data, null);
MessageBox.Show(oList.Count.ToString())
}
}
If I put a breakpoint on the GetValue line, the prop parameter knows that it's a list of "myclass" items with three elements. I just can't cast it to either a list of objects (which would be fine) or cast it to a list of actual "myclass" elements which would be even better. How do I cast the return value of PropertyInfo.GetValue (an object) to its List?

First of all, it's not enough (or needed in this case at all) to check the namespace. You can check if prop.PropertyType is an instance of ICollection (you can use IsAssignableFrom). I'm suggesting ICollection because you only seem to care about the Count.
You can then cast it to an ICollection (non-generic) and run Enumerable.Cast, like:
IEnumerable<MyClass> res = ((ICollection)prop.GetValue(data,null)).Cast<MyClass>();
MessageBox.Show(res.Count().ToString());
The advantage over converting directly to List is that this will work with any collection. But if you don't need that, you can try what the other answer suggests.

did you try
prop.GetValue(data, null) as List<YourClass>;

I guess you want contravariance.
Are you trying to do so?
List<object> list = (List<Product>)object;
List<object> and List<Product> wouldn't be treated as the same type.
C# 4.0 introduced covariance and contravariance for interface and delegate generic parameters, but anyway, IList<T> doesn't have contravariance.
In my humild opinion, I believe you'll need to reconsider your object graph!
PD: Just comment out if you want guidance for that!

Related

Passing string list to F# asp.Net api

I actually solved my problem before posting, but I wonder if there are any better solutions?
Also if there is somewhere where there is a way to use list as-is?
I am writing a simple get endpoint if F# which needs to accept a list of strings as an argument.
I take that list as the input to a query that runs as expected, I am not worried about that part.
The problem I am facing is as follows (minimal implmenetation):
When I define the endpoint as:
[<HttpGet>]
member _.Get() =
processStrings [ "test"; "test2" ]
it returns as expected.
When I change it to:
[<HttpGet>]
member _.Get([<FromQuery>] stringList: string list) = processStrings stringList
I get an error:
InvalidOperationException: Could not create an instance of type 'Microsoft.FSharp.Collections.FSharpList`1[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Record types must have a single primary constructor. Alternatively, give the 'stringList' parameter a non-null default value.
Which doesn't make much sense to me, as I am using a list of strings, which in C# at least defaults to an empty list.
So I assume this comes down to how C# and F# interpret these signatures, but I am not sure how to resolve it.
I tried this signature and received the same error as above....
member _.Get( [<Optional; DefaultParameterValue([||]); FromQuery>] stringList: string list) = processStrings stringList
In the end using the following did solve the problem.
member _.Get( [<Optional; DefaultParameterValue([||]); FromQuery>] stringList: string seq) = processStrings stringList
I assume it was solved because seq is just IEnumerable, and then presumable list isn't just List from C# (mutable vs immutable). But is there a way to use an F# list in [FromQuery] parameters? Would [FromBody] have just worked? (No is the tested answer) Is there a way to add a type provider for an endpoint like this?
Is there something else I am missing here? Mine works now, but I am curious to the implications of the above.
I have not tested this, but I would assume that ASP.NET does not support F# lists as arguments. I would guess that taking the argument as an array would be much more likely to work:
[<HttpGet>]
member _.Get([<FromQuery>] stringList: string[]) =
processStrings (List.ofArray stringList)

How to correct the objection about dymanic Object type by FlexPMD?

I have the code in one of my flex file used as labelFunction in a DataGrid.
When I run the FlexPMD to do the code review, it generates an objection about the dynamic type object used in the following method signature and it suggests to use strongly type object.
public function getFormattedCreatedTime(item:Object, column:DataGridColumn):String {
var value:Date=item[column.dataField];
return dateFormatter.format(value);
}
Does anyone know how to rectify it?
Thanks
You have the answer in your question - just use a strongly type object, or perhaps an interface if item can have various types.
But basically there's nothing wrong with using dynamic type objects as long as you know what you're doing. I'd say just ignore the error.
In this case it would be of course possible to type item to something less generic than Object, but some times you can't, or Object is exactly the right type, in this case you can use //NOPMD comment - it will instruct the PMD validator to skip the definition. Of course the good practice is to also explain the reason you used //NOPMD.

Unable to Bind warning: class is not an IEventDispatcher

I found another similar question, but don't quite follow the explanation there, and not sure if it applies the same to me.
I am getting the error:
warning: unable to bind to property 'Description' on class 'Object' (class is not an IEventDispatcher)
this is only when the data is bound to a List as an ArrayList, though. I had it in a Datagrid before (just as an Array) and it did not cause any issue. I'm not expecting to be able to bind any data back to the class 'object' not even sure which object exactly it's referring to.
My list data-provider is an ArrayList.. populated by a result event from an SQL query contained in another class:
private function loadDayComplete():void
{
var Meals:Array = _day.MealResults;
var MealsListResult:ArrayList = new ArrayList(Meals);
MealPanelDataGrid.dataProvider = Meals;
MealListView.dataProvider = MealsListResult;
{
The day class I have is a data holder to get all the data (from several tables) for a 24 hour span.. I have classes for each individual datatype for editing them.
But I'm not sure do I even need to worry about the warning if I don't plan on editing the values? it completely spams the console though whenever I touch anything, so I really would like to get rid of it.
I tried an object proxy as I saw described elsewhere but nothing changed. And I'm pretty confused why it's suddenly an issue on a list component when it wasn't on a datagrid... The text is in label fields right now anyway, which can't even be edited.
The objects causing this warning are probably items inside Meals array.
Make sure that these items are strongly typed (Data Transfer Objects / Value Objects patterns) and that Description field is marked [Bindable].
Depending on the remoting mechanism you are using you may be able to use something like makeObjectsBindable flag which replaces returned Object items with bindable ObjectProxy instances.
But I'll advise strong typing anyway.
You can get rid of it by making your dataProvider an EventDispatcher: ObjectProxy is an EventDispatcher. It will automatically wrap your data to a specified or infinite depth (default behavior).
metaPanelDataGrid.dataProvider = new ObjectProxy(meals);
It's basically the same thing as with ArrayCollection but deeper.

Getting all info from a Flex object/module

I'm wondering if there's any reasonable way to get a reference to an object in Flex, and look through everything in every sub object (every property and everything). That is, I want to know if I can completely map all of the data within an object, from another object. I'm aware that this wouldn't work for private (or protected) members, but for anything public, it should be possible, correct?
Use describeType for class instances, and
for (var str:String in obj) { trace (str+":"+obj[str]); }
for simple Objects.

How to use FormView in order to insert complex entity framework objects

I'm trying to use formview in order to do insert of a new entity object (called Customer)
Customer has a reference to another entity called Address.
How can I fill both of them in the same formview?
Thanks.
After looking more into it, it seems like the problem is in the ConvertProperties method of EntityDataSourceView.
Using reflector I've found out that the problem was in the line:
PropertyDescriptor pd = propertyDescriptors.Find(str, false);
(this codeline takes the inserted property name, and convert it to a descriptor)
when str = "Address.Address1" the function returns null.
I've took a look at propertyDescriptors.properties and it seems like Address.Address1 doesn't exist. Only Address.ID and Address exist.
I took a look at the population of propertyDescriptors and it seems like there is no way to change that. Or in other words, it seems like there is no solution to the problem.
bummer.
Actually there is a solution. Flatten the two objects into one. Create a CustomerViewModel object that includes all of the fields of the two objects. Then at databinding bind to the CustomerViewModel.

Resources