I have several methods that populate a SQLCommand objects parameter collection from an object like this
if (!String.IsNullOrEmpty(SearchObj.FirstName))
{
command.AddParameter(Fields.FirstName, SearchObj.FirstName);
}
if (!String.IsNullOrEmpty(SearchObj.LastName))
{
command.AddParameter(Fields.LastName, SearchObj.LastName);
}
if (!String.IsNullOrEmpty(SearchObj.EmailAddress))
{
command.AddParameter(Fields.EmailAddress, SearchObj.EmailAddress);
}
if (SearchObj.JobRoleId > -1)
{
command.AddParameter(Fields.JobRoleId, SearchObj.JobRoleId);
}
This can get messy as the object can have up to about 20 properties. Is there anyway using reflection to loop through each of these properties and add them all to the Sqlcommand objects Parameter collection? Bearing in mind it treats strings different to ints in that it only adds a string if its not null or empty and it only adds an int if its greater than -1.
I've not used much reflection before, so a point in the right direction would be great.
Thanks
Try using the methods listed here:
How to get the list of properties of a class?
and then loop over them adding them as you see fit.
Related
Here is a sample code:
public class Example3 {
class Point {
int x, y; // these can be properties if it matters
}
class PointRepresentation {
Point point; // this can be a property if it matters
public PointRepresentation(Point point) {
this.point = point;
}
}
Example3() {
ObservableList<Point> points = FXCollections.observableArrayList();
ObservableList<PointRepresentation> representations = FXCollections.observableArrayList();
points.forEach(point -> representations.add(new PointRepresentation(point)));
}
}
I have a data holder Point and a data representor PointRepresentation. I have a list of points and i would like that for each point in the list there would be an equivalent representation object in the second list. The code I gave works for the initialization but if there is any change later the above will not update.
What I am doing now is using a change listener to synchronize the lists (add and remove elements based on the change object) and it's OK but i am wondering if there's a simpler solution. I was looking for something like a "for each bind" that means: for each element in one list there is one in the other with the specified relation between them [in my case its that constructor]. In pseudocode:
representations.bindForEach(points, point -> new PointRepresentation(point));
Things I looked at: extractors for the list but that sends updates when a property in the objects they hold change and not when the list itself changes. So in my case if x in the point changes i can make an extractor that notifies it. Another thing I looked at is http://docs.oracle.com/javase/8/javafx/api/javafx/beans/binding/ListBinding.html, so maybe a custom binding does it but I don't know if it's simpler.
Also is there a similar solution for arrays instead of lists? i saw the http://docs.oracle.com/javase/8/javafx/api/javafx/collections/ObservableArray.html as a possibility.
The third-party library ReactFX has functionality for this. You can do
ObservableList<Point> points = FXCollections.observableArrayList();
ObservableList<PointRepresentation> representations = LiveList.map(points, PointRepresentation::new);
This will update representations automatically on add/remove etc changes to points.
Web services cannot return an anonymous type.
If you are building a LINQ query using classes through a datacontext... you cannot construct instances of those classes in a query.
Why would I want to do this? Say I want to join three "tables" or sets of objects. I have three items with a foreign key to each other. And say the lowest, most detailed of these was represented by a class that had fields from the other two to represent the data from those. In my LINQ query I would want to return a list of the lowest, most detailed class. This is one way I have decided to "join some tables together" and return data from each of them via LINQ to SQL via a WebService. This may be bad practice. I certainly do not like adding the additional properties to the lowest level class.
Consider something like this... (please ignore the naming conventions, they are driven by internal consideration) also for some reason I need to instantiate an anonymous type for the join... I don't know why that is... if I do not do it this way I get an error...
from su in _dataContext.GetTable<StateUpdate>()
join sfs in _dataContext.GetTable<SystemFacetState>()
on new { su.lngSystemFacetState } equals new { lngSystemFacetState = sfs.lngSystemFacetState }
join sf in _dataContext.GetTable<SystemFacet>()
on new { sfs.lngSystemFacet } equals new { lngSystemFacet = sf.lngSystemFacet }
join s in _dataContext.GetTable<System>()
on new { sf.lngSystem } equals new {lngSystem = s.lngSystem}
select new
{
lngStateUpdate = su.lngStateUpdate,
strSystemFacet = sf.strSystemFacet,
strSystemFacetState = sfs.strSystemFacetState,
dtmStateUpdate = su.dtmStateUpdate,
dtmEndTime = su.dtmEndTime,
lngDuration = su.lngDuration,
strSystem = s.strSystem
}
).ToList();
Notice I have to build the anonymous type which is composed of pieces of each type. Then I have to do something like this... (convert it to a known type for transport via the web service)
result = new List<StateUpdate>(from a in qr select(new StateUpdate
{
lngStateUpdate = a.lngStateUpdate,
strSystemFacet = a.strSystemFacet,
strSystemFacetState = a.strSystemFacetState,
dtmStateUpdate = a.dtmStateUpdate,
dtmEndTime = a.dtmEndTime,
lngDuration = a.lngDuration,
strSystem = a.strSystem
}));
It is just awful. And perhaps I have created an awful mess. If I am way way off track here please guide me to the light. I feel I am missing something fundamental here when I am adding all these "unmapped" properties to the StateUpdate class.
I hope someone can see what I am doing here so I can get a better way to do it.
You can create a 'dto' class which just contains the properties you need to return and populate it instead of the anonymous object:
public class Result
{
public string lngStateUpdate
{
get;
set;
}
... // other properties
}
then use it like this:
from su in _dataContext.GetTable<StateUpdate>()
...
select new Result
{
lngStateUpdate = su.lngStateUpdate,
... // other properties
}
Nitpick note - please ditch the Hungarian notation and camel casing for properties :)
I think the answer is to create another object to serve as a DTO. This object would not be mapped to the data context and can contain fields that cross the mapped objects. This solves the problems of repetitive properties in the mapped objects, and allows for instantiation of the DTO class in the query as it is not mapped.
FYI: with respect to the problem with the join- I revisited that and I think I may have had the inner and outer components of the join switched around before.
Let's Say I Have This Class:
package{
import flash.display.Sprite;
public class Main extends Sprite{
public function Main(){
trace(getAverage(1,2,3));
trace(getAverage(1,2,3,4));
trace(getAverage(1,2,3,4,5));
}
public function getAverage (...numbers) {
var total = 0;
for (var i = 0; i < numbers.length; i++) {
total += numbers [i];
}
return total / numbers.length;
}
}
}
How do I accomplish the "opposite" of this? Namely, how could I now CALL 'getAverage' with a dynamic number of paraemters?
For instance, if I wanted to do something LIKE:
var r:int=Math.random()*6;
var a:Array=new Array();
for (i:int=0;i<r;i++) {
a[i]=Math.random()*22;
}
// Now I have 'r' Number Of Parameters Stored In 'a'
// How Do I Call getAverage, with all the values in 'a'??
// getAverage(a) isn't right, is it?
// I'm looking for something similar to getAverage(a[0],a[1],a[...]);
var av:Number=getAverage(???);
What I want to know, is if I have a function that takes a variable number of arguments, that's great, but how can I CALL IT with a variable number of arguments, when that number isn't known at runtime? Possibly it's impossible... I'm just not sure, since 'callLater' seems to be able to take an array and generate a dynamic number of parameters from it somehow...
NOTE: Answers consisting solely of "Why Do You Want To Do This?", will be downvoted.
P.S. This IS NOT about calculating Averages! I REALIZE There Are Way Simpler Ways Of Doing All Of This! (I could just write getAverage to accept a single array as its only parameter) The Above is just an EXAMPLE to Illustrate my Question. HOW TO PASS A DYNAMIC NUMBER OF PARAMETERS TO A FUNCTION?
Is this what you're looking for?
var av:Number = getAverage.apply(null, a);
Dave is correct. You can use the apply method of a function to pass in an Array of arguments.
Here is a better explanation of how it works and what the arguments of apply are:
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/Function.html
Also note that you can use the call method to do the same thing but using ...args (comma-delimited list) instead, but apply would be more suitable to your situation.
The problem with your question is that the arguments object is already an Array and using (...args) already provides you with a dynamic way to pass any number of arguments you require. Sorry about the previous answer, wasn't thinking straight...
You can create an array or an object with those parameters and pass that object to that function. That's just normal.
Flash has a rather strong introspection capabilities. So, instead of passing a number of objects, you just pass a single dynamic object with any number of attributes you need:
var ob:Object={arg1:"value1", arg2:8};
var arg:String="arg4";
ob["arg3"]=8;
ob[arg]=18;
trace (ob.hasOwnProperty("arg1"));
trace (ob.arg3);
trace (ob.arg4);
That should cover just about any use case you might need. The downside is that this allows for some rather clever and hard to trace bugs. :-)
Does anyone have any recommendations for working with name/value pairs in Flex?
Context:
I want to create a Flex UI for updating a database table. I want the UI to contain the field name(read only) and current field value (which will be editable). Im using the WebService component to retrieve the field value and then asssigning it to an object with the field name hardcoded e.g.
private function resultHandler(event:ResultEvent):Object
{
var resultsObj:Object;
resultsObj = {
name:event.result.name as String,
This approach however is adding the dependency that the table structure/field names will never change. Using the object type also requries that i write my own algorithm to sort the output.
I'm not sure I understand the issue.
If you want to avoid dependency of the properties returned from the event at this point, simply use the event.result object, which is already an associative array.
As for sorting, we would need more context on what you are attempting to sort.
That's pretty simple. Don't use for each in loop. Use For-In Loop
Demo is shown below.
var dicEntry:Object = new Object();
dicEntry["Name"] = "Raj";
dicEntry["sal"] = 10000;
dicEntry["age"] = 33;
for(var key:Object in dicEntry)
{
trace("Object Key: "+key+" Object Value: +dicEntry[key]);
}
That's it.
Is there a simple way to retrieve the length of an associative array (implemented as an Object) in ActionScript 3.0?
I understand that there are two primary ways of creating associative arrays in AS3:
Use a Dictionary object; especially handy when the key does not need to be a string
Use an Object, and simply create properties for each desired element. The property name is the key, and the value is, well, the value.
My application uses approach #2 (using the Object class to represent associative arrays).
I am hoping there is something more native than my for loop, which manually counts up all the elements.
You have to count them in a for loop as you do. Of course, you could make a class and stick the for loop in that class.
For some great implmentations of Collections in AS3, check these guys.
Edit 2013 Not surprisingly, links do break after time. Try this new one: http://www.grindheadgames.com/get-the-length-of-an-object.
Doing a few tests on this has actually surprised me. Here's normal use of an Array:
var things:Array = [];
things.push("hi!");
trace(things.length);
// traces 1
trace(things);
// traces hi!
Here's if we set a value to a string:
var things:Array = [];
things["thing"] = "hi!";
trace(things.length);
// traces 0
trace(things);
// traces an empty string
trace(things["thing"]);
// traces hi!
Basically if you add things using strings you're setting properties rather than actually adding to the array. Makes me wonder why Array is dynamic in this way.
So... yeah count the items with a for ... in loop!
I think you're stuck with counting them "manually".
An option would be to wrap the whole thing in a class and keep a separate variable that you update as you add/remove.
var count:int;
var key:String;
for (key in myObject)
{
count++;
}
trace ("myObject has this many keys in it: " + count);
or, alternatively, the for-each syntax (I haven't tested to see which is faster)
for each (var o:* in myObject)
{
count++;
}