Accessing pointer object properties in Vala - pointers

I have refactored a bit my code, so i need a pointer that could contain multiple liste types :
owl_list = new Gee.LinkedList<OpenWithAction> ();
a_list = new Gee.LinkedList<OpenAppAction> ();
Gee.List* any_list = null;
So i have a pointer any_list which i can use to access either owl_list or a_list (depending on a switch no present here, but assume there is)
if (!any_list.size)
return null;
But this will fail as valac throws at me error: The name `size' does not exist in the context of `Gee.List*'
if (!any_list.size)
I haven't done any C,C++ since a very long time and I'm no vala expert, since i use more typeless languages, but is there any way this could work ?
EDIT:
I just tried
fieldType = OpenWithAction.get_type();
if (!(any_list as Gee.List<fieldType>).size)
error: The type name `fieldType' could not be found
if (!(any_list as Gee.List<fieldType>).size)
Obviously I'm doing something wrong, what i'm trying to do is : Vala: determine generic type inside List at runtime, i just can"t manage to implement it.
return null;
EDIT 2:
I just solved partially my problem :
As said by #jens-mühlenhoff, yes OpenWithAction and OpenAppAction have a common ancestor and it is GLib.Action
So all i had to do is declare :
Gee.List<Action> any_list = null;
instead of
Gee.List* any_list = null;
now foreach (var action in any_list) is working, but i'm still getting an error with
if (any_list->size == null)
return null;
error: The name `size' does not exist in the context of `Gee.List<Synapse.Action>?'
if (any_list->size == null)
another try is :
if (!any_list.size)
return null;
Operator not supported for `int'
if (!any_list.size)

any_list is a pointer, so you can't use the . operator. Try any_list->size.

Two things i was doing wrong :
1-
Like in C# i should not have used a pointer if not needed. So using :
Gee.List<Action> any_list = null; is just working fine. The explanation is that OpenWithAction and OpenAppAction have a common ancestor class, So declaring a List with that type is just working fine ( on the other hand i don't know in the case they didn't have a common ancestor).
2- int type can't be used as bool type so if (any_list.size == 0) would work whereas if (!any_list.size) would throw an error
Thanks every one for helping :)

Related

Cannot implicitly convert type 'System.Linq.IQueryable to System.Data.Entity.DbSet<>

I receive the following error when I try to run my code. I haven't managed to solve it yet, please Help:
edit: Marked with * where it fails.
>
public IQueryable<Video> GetVideos([QueryString("id")] int? categorieId)
{
var _db = new TeleviziuneAcademicaAspSilverlight.Models.VideoContext();
IQueryable<Video> query = *_db.Videos;*
if (categorieId.HasValue && categorieId > 0)
{
query = query.Where(v => v.CategorieID == categorieId);
}
return query;
Change
IQueryable<Video> query =
to
IQueryable<Appname.Models.Video> query =
The reason for your error is that you have the type Video defined twice and because of using a short type name you accidentally reference not the one Video you should.
Also change it in the method's return value
public IQueryable<Appname.Models.Video> GetVideos( ... )
You seem to have two classes called Video. If you need both, you'll need to project from one to the other before your return statement:
return query.Select(dbVideo => new Appname.Video()
{
Prop1 = dbVideo.Prop1,
Prop2 = dbVideo.Prop2,
// etc.
});
Though you'll probably need to change the return type to an IEnumerable<> if you do that.
If you can just work with Appname.Models.Video, change IQueryable<Video> to IQueryable<Appname.Models.Video> in the method signature and the method body.

ILGenerator. Whats wrong with this Code

I am trying to build a dynamic Property Accessor. Want something which is like really fast as close to calling the actually Property. Dont want to go the Reflection route as its very slow. So i opted to using DynamicAssembly and inject IL using ILGenerator. Below is the ILGenerator related code which seems to work
Label nulllabel = getIL.DefineLabel();
Label returnlabel = getIL.DefineLabel();
//_type = targetGetMethod.ReturnType;
if (methods.Count > 0)
{
getIL.DeclareLocal(typeof(object));
getIL.DeclareLocal(typeof(bool));
getIL.Emit(OpCodes.Ldarg_1); //Load the first argument
//(target object)
//Cast to the source type
getIL.Emit(OpCodes.Castclass, this.mTargetType);
//Get the property value
foreach (var methodInfo in methods)
{
getIL.EmitCall(OpCodes.Call, methodInfo, null);
if (methodInfo.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
}
getIL.Emit(OpCodes.Stloc_0); //Store it
getIL.Emit(OpCodes.Br_S,returnlabel);
getIL.MarkLabel(nulllabel);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Stloc_0);
getIL.MarkLabel(returnlabel);
getIL.Emit(OpCodes.Ldloc_0);
}
else
{
getIL.ThrowException(typeof(MissingMethodException));
}
getIL.Emit(OpCodes.Ret);
So above get the first argument which is the object that contains the property. the methods collection contains the nested property if any. for each property i use EmitCall which puts the the value on the stack and then i try to box it. This works like a charm.
The only issue is if you have a property like Order.Instrument.Symbol.Name and assume that Instrument object is null. Then the code will throw an null object exception.
So this what i did, i introduced a null check
foreach (var methodInfo in methods)
{
getIL.EmitCall(OpCodes.Call, methodInfo, null);
getIL.Emit(OpCodes.Stloc_0);
getIL.Emit(OpCodes.Ldloc_0);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Ceq);
getIL.Emit(OpCodes.Stloc_1);
getIL.Emit(OpCodes.Ldloc_1);
getIL.Emit(OpCodes.Brtrue_S, nulllabel);
getIL.Emit(OpCodes.Ldloc_0);
if (methodInfo.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
}
Now this code breaks saying That the object/memory is corrupted etc. So what exactly is wrong with this code. Am i missing something here.
Thanks in Advance.
Previously, if you had consecutive properties P returning string and then Q returning int, you would get something like this:
...
call P // returns string
call Q // requires a string on the stack, returns an int
box
...
Now you have something like this:
...
call P // returns string
store // stores to object
... // load, compare to null, etc.
load // loads an *object*
call Q // requires a *string* on the stack
store // stores to object *without boxing*
...
So I see two clear problems:
You are calling methods in such a way that the target is only known to be an object, not a specific type which has that method.
You are not boxing value types before storing them to a local of type object.
These can be solved by reworking your logic slightly. There are also a few other minor details you could clean up:
Rather than ceq followed by brtrue, just use beq.
There's no point in doing Stloc_1 followed by Ldloc_1 rather than just using the value on the stack since that local isn't used anywhere else.
Incorporating these changes, here's what I'd do:
Type finalType = null;
foreach (var methodInfo in methods)
{
finalType = methodInfo.ReturnType;
getIL.EmitCall(OpCodes.Call, methodInfo, null);
if (!finalType.IsValueType)
{
getIL.Emit(OpCodes.Dup);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Beq_S, nulllabel);
}
}
if (finalType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
getIL.Emit(OpCodes.Br_S, returnLabel);
getIL.MarkLabel(nulllabel);
getIL.Emit(OpCodes.Pop);
getIL.Emit(OpCodes.Ldnull);
getIL.MarkLabel(returnlabel);
Note that we can get rid of both locals since we now just duplicate the top value on the stack before comparing against null.

Is there anything wrong with this database class's execute query function?

So I have this old code being used, that runs simple ExecuteNonQuery command for database calls. I'm using DbConnection, DbTransaction and other System.Data.Common commands.
I seem to get a lot of Null Reference errors whenever I use the function in certain parts of the project, though it seems fine in other parts. I think it has to do with opening connections manually or some problem with calling it, but I'm wondering if the function itself is badly designed originally (shouldn't there be a way to fix any problems in the way it is called?)
I feel when transactions are involved, these null reference errors come up more often, I think the error I get is null exception at "_command = _db.GetStoredProcCommand(storedProcedure);" inside the following function. But that stored procedure does exist, so it makes no sense.
public List<OutputParameter> execute(String storedProcedure, StoredProcedureParameter[] sqlParameters)
{
try
{
List<OutputParameter> outputParameters = new List<OutputParameter>();
_command = _db.GetStoredProcCommand(storedProcedure);
for (int x = 0; x < sqlParameters.GetLength(0); x++)
{
if (sqlParameters[x] != null)
{
StoredProcedureParameter sqlParameter = sqlParameters[x];
String param = sqlParameter.ParameterName;
DbType dbType = sqlParameter.DbType;
object value = sqlParameter.Value;
if (sqlParameter.IsOutputParam)
{
_db.AddOutParameter(_command, param, dbType, 32);
OutputParameter outputParameter = new OutputParameter(param);
outputParameters.Add(outputParameter);
}
else
_db.AddInParameter(_command, param, dbType, value);
}
}
if (_transaction == null)
_db.ExecuteNonQuery(_command);
else
_db.ExecuteNonQuery(_command, _transaction);
foreach (OutputParameter op in outputParameters)
{
op.ParameterValue = _db.GetParameterValue(_command, op.ParameterName);
}
return outputParameters;
}
catch (SqlException sqle)
{
throw new DataAccessException(sqle.ToString());
}
catch (Exception e)
{
throw new DataAccessException(e.ToString());
}
}
Your _command variable appears to be a field and as such a shared member.
As such your code is very susceptible to multithreading issues (if two functions call this class with different stored procedures, what happens?).
A Command should also be closed and disposed of properly, which is not happening in your code, not explicitly anyways.
If you are getting a null reference exception in the line _command = _db.GetStoredProcCommand(storedProcedure); then the only thing that can be null there is _db. The storedProcedure is just a parameter and _command could happily be null without a problem.
Since you aren't actually doing anything in the code to make sure that _db exists and is valid, open, etc. then this is most likely the problem.

the correct actionscript to find if object already exists (with a local variable defined inside conditional)

I have a Rect object that I'd like to create and set its properties only once. After that, I want to just modify its properties since it already exists. This is my general idea
if(theRect == undefined){
Alert.show("creating");
var theRect:Rect = new Rect();
//then set properties
addElement(theRect); //then add it using addElement because addChild() does not work
} else {
Alert.show("updating");
//no need to create it since it's already been created
//just access and change the properties
}
I tried several ways and combinations for the if conditional check:
if(theRect == undefined){
if(theRect == null){
declaring and not declaring `var theRect:Rect;` before the if check
declaring and instantiating to null before the if check `var theRect:Rect = null;`
but can't get the desired effect. Everytime this code block runs, and depending on which version I've used, it either gives me a "can't access null object" error or the if statement always evaluates to true and creates a new Rect object and I get the "creating" Alert.
What's the right way of creating that Rect but only if doesn't exist?
You have some scoping issues in the code you presented.
What I think you want to do is:
var theRect:Rect;
...
if(theRect == null)
{
theRect = new Rect();
...
}
...
You need to first declare theRect, but you don't have to create it. You can instantiate it lazily later by checking if it is null.
The way you have it set up, you created a local version of theRect inside your if statement that would not be visible elsewhere. You will also get an error trying to access theRect if you did not declare it beforehand.

Flex 3.2 casting problem

I'm newish to flex an have recently hit a snag casting.
this is the code I'm running.
/**
* return background definition depending on time
*/
private function findBackgroundItem( relativeTime : Number ) : CSBackgroundItem
{
if( this.backgroundItems == null ) return null;
var result :CSBackgroundItem = null;
var relative:Date = new Date(relativeTime);
for( var i : Number = 0; i < this.backgroundItems.length; i++ )
{
// backgroundItems is an Ilist of CSBackgroundItem.
var colourItem : CSBackgroundItem = CSBackgroundItem( this.backgroundItems.getItemAt( i ) );
// other stuff here
}
return result;
}
The problem occurs when the IList.getItemsAt() result is cast to the CSBackgroundItem variable colourItem. The following error is thrown
TypeError: Error #1034: Type Coercion failed: cannot convert com.mystuff::CSBackgroundItem#650e8dd1 to com.mystuff.CSBackgroundItem.
If I use the 'as' keyword I get cast results in the colourItem being null. Using the debugger shows that the list is not empty and is indeed populated with CSBackgroundItem objects.
Now this is the wacky bit.. this code works, the first time the module it's in loads.. subsequent loads (after unloading it) throw the exception.
Can anyone shed any light on why this might happen?
FYI, a type loaded into a child ApplicationDomain can be cast to a type (that it extends/implements) in the parent ApplicationDomain.
Eg.
loader.applicationDomain = ApplicationDomain.currentDomain; // parent domain
loader.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain); // child domain
loader.applicationDomain = new ApplicationDomain(); // new domain
I think I may have found the answer..
My guess is the module is loading in a different ApplicationDomain.. which would mean you can't cast from the same type in the current domain..
As I understand this is vaguely similart to different Java ClassLoaders loading the same class.
I'll post again once I've confirmed it
Yup.. that works..
here is the fix i used in MXML style..
<mx:ModuleLoader id="loader" x="10" y="10" width="100%" height="100%" applicationDomain="{ApplicationDomain.currentDomain}"/>
the equivilant actionscript would be
loader.applicationDomain = ApplicationDomain.currentDomain;

Resources