VBA: how to test for object equality (whether two variables reference the same object) - oop

What is the operator or function to test whether two variables of the same custom object type refer to the same object? I've tried
If myObject = yourObject Then
But get a runtime error 438 object doesn't support this property or method. I'm guessing that's telling me to override the '=' operator to test if all the fields of the two objects have the same value. But what I want is to test whether they are the same object.

I'm guessing that's telling me to override the '=' operator to test if all the fields of the two objects have the same value.
No, it tells you the objects don't have a default property which would have been called otherwise, and the returned results compared.
You test reference equality with Is
If myObject Is yourObject Then

You need to serialize the objects somehow and then compare attribute by attribute values. The "is" operator is as dumb as it gets, it only matches if another object is the same instance assigned to the compared variable.
I suggest using a jsonStringify library. I adapted one for my DexTools.xlam open source project https://github.com/dexterial/Dextools/tree/master/Main starting from the Parsing JSON in Excel VBA post. It has much more added features since I added quite a few other excel objects serialization/hashing options and it is made using the vba test driven development that DexTools incorporates. It is still work in progress so dont expect miracles

Related

Show all variables and their values in VBA during runtime

In my current project in Access VBA, I created a window which works like a console and now I am trying to add a possibility to display any public variable. It should work like:
Show_var [variable_name]
So it should be like in the direct window where i can type:
? pVar.variable_A
I found out that using
Application.VBE.ActiveVBProject.VBComponents(11).CodeModule.CountOfLines
I can display the number of lines within a module or form so I thought perhaps I could somehow find the variables there, cycle through them and when the correct one is found, its value can be shown. OFC I could make a Select Case Statement where all variables are included but that is not the way I want to do it because it is complicated and must be changed every time update my public variable list.
There are so many problems that I think you are out of luck. Let me just list some of them:
There is no way to get a list of all variables - that would mean you would need access to the internal symbol table.
As a consequence, you would have to read the code (CodeModule lets you read the code of a module), and write an own parser to fetch all declarations (hopefully you use Option Explicit)
AFAIK, the is no method that can access the content of a variable via it's name.
Even if there would be any such method: What would you do with different data types, arrays and especially with objects.
If a user runs into problems, often it is a runtime error. If you don't handle that errors with some kind of error handler, the only option if a user cannot enter the debugger is to press "End" - which would destroy the content of all variables.
You have to deal with scope of variables, you can have several variables with the same name and you will likely have lots of variables that are out of scope in the moment you want to dump them.

What is the point of CTypeDynamic?

I'm using reflection to serialize an object. Getting the values as objects is a real murder on performance due to late binding penalties. CType / DirectCast can get rid of most of it but I can't feed a type variable into it so currently I'm using a switch case block on the type variable to select the correct DirectCast.
It came to my attention that CTypeDynamic exists and takes type variables but the return type is Object so... it converts an object into an object, cool. That got me wondering, what is the purpose of this function?
The CTypeDynamic function looks for dynamic information and performs the cast/conversion appropriately. This is different from the CType operator which looks for static information at compile time or relies on the types being IConvertible.
This function examines the object at runtime including looking for Shared (aka static) custom operators. As always, if you know the type then use CType, but if you need dynamic casting then you need to use CTypeDynamic.
More information here: http://blogs.msmvps.com/bill/2010/01/24/ctypedynamic/

LINQ to Entities does not recognize the method [Type] GetValue[Type]

I've a simple class like this:
Public Class CalculationParameter{
public Long TariffId{get;set;}
}
In a workflow activity, I've an Assign like this:
(From tariffDetail In db.Context.TariffDetails
Where tariffDetial.TariffId = calculationParameter.TariffId).FirstOrDefault()
Dto is passed to Activity as an Input Argument.
It raise following error and I'm wondering how to assign Id. Any Idea?
LINQ to Entities does not recognize the method 'Int64
GetValue[Int64](System.Activities.LocationReference)' method, and this
method cannot be translated into a store expression.
How can I assign the calculationParameter.TariffId to tariffDetial.TariffId?!
UPDATE:
Screen shot attached shows that how I'm trying to assign calculationParameter.TariffId to tariffDetail.TariffId (car.Id = Dto.Id) and the query result should assign to CurrentTrafficDetail object.
Here's your problem. I don't know if there is a solution to it.
As you said in a (now deleted, unfortunately necessitating that I answer) comment, the exception you're getting is
LINQ to Entities does not recognize the method Int64 GetValue[Int64](System.Activities.LocationReference) method, and this method cannot be translated into a store expression.
in your Linq query, calculationParameter is a Variable defined on the workflow. That Variable is actually an instance that extends the type System.Activities.LocationReference and NOT CalculationParameter.
Normally, when the workflow executes, the LocationReference holds all the information it needs to find the value which is assigned to it. That value isn't retrieved until the last possible moment. At runtime, the process of retrieval (getting the executing context, getting the value, converting it to the expected type) is managed by the workflow.
However, when you introduce Linq into the mix, we have the issue you are experiencing. As you may or may not know, your expression gets compiled into the extension method version of the same.
(From tariffDetail In db.Context.TariffDetails
Where tariffDetial.TariffId = calculationParameter.TariffId)
.FirstOrDefault()
is compiled to
db.Context.TariffDetails
.Where(x => x.TariffId = calculationParameter.TariffId)
.FirstOrDefault();
When this executes, L2E doesn't actually execute this code. It gets interpreted and converted into a SQL query which is executed against the database.
As the interpreter isn't omniscient, there are a well defined set of limitations on what methods you can use in a L2S query.
Unfortunately for you, getting the current value of a LocationReference is not one of them.
TL:DR You cannot do this.
As for workarounds, the only thing I think you can do is create a series of extension methods on your data context type or add methods to your CalculationParameter class that you can call from within the Expression Editor. You can create your Linq to Entities queries within these methods, as all types will already have been dereferenced by the workflow runtime, which means you won't have to worry about the L2E interpreter choking on LocationReferences.
*Edit: A workaround can be found here (thanks to Slauma who mentioned this in a comment on the question)

How can I print a servlet context attribute in EL?

Is there a way I can get a attribute set in ServletContext in EL so that it ends up as a JavaScript variable?
I am setting it as
context.setAttribute("testing.port", "9000");
I tried retrieving it like
alert("port" +'${testing.port}');
I am just getting a blank.
The problem is the period (.) in the key name. EL interprets the period as a call to an accessor method named getPort1 on whatever object testing references. Fetch the value from the appropriate implicit object:
${applicationScope['testing.port']}
or just use a different key:
${testingPort}
1Yes, this is a simplification of what really happens. It may also look for a predicate getter named isPort, or try Map#get("port").

How to I pass a checkbox value by reference with CLI?

I have a GUI app written in C++/CLI which has a load of configurable options. I have some overloaded functions which grab values from my data source and I'd like to connect my options to those values.
So here's a couple of data retrievers:
bool GetConfigSingle(long paramToGet, String^% str, char* debug, long debugLength);
bool GetConfigSingle(long paramToGet, bool^% v_value, char* debug, long debugLength);
I was hoping to pass in the checkbox's Checked getter/setter as follows:
result = m_dataSource->GetConfigSingle(CONFIG_OPTION1, this->myOption->Checked, debug, debugLen);
...but for some reason I get an odd compiler error which suggests the Checked value isn't being passed as I'd expect:
1>.\DataInterface.cpp(825) : error C2664: 'bool DataInterface::GetConfigSingle(long,System::String ^%, char*, long)' : cannot convert parameter 2 from 'bool' to 'System::String ^%'
Previously this code passed the checkbox in and modified the values itself, but I'm keen to break the dependency our data collection currently has on windows forms.
So what am I missing here?
[Edit] I've filled out the function definitions as they originally were to avoid confusion - my attempt to reduce the irrelevent information failed.
I'm fairly certain that the CheckBox getter / setter returns a bool.
Figured I'd clarify my comments from above and make it a "real" answer...
When you call Checked, what you're getting back as a return value is a bool that represents the current state of the CheckBox. It is not, however, a reference to the actual data member that holds the CheckBox's state. In fact, a properly encapsulated class shouldn't give access to it. Furthermore, since Checked returns a bool by value, that bool is a temporary object that doesn't necessarily exist by the time GetCongigSingle is called.
This leaves you with several options. Either pass the bools by value, and later set the CheckBox's state, or pass the CheckBox itself by reference and "check" it wherever you want.
The two overload of the method GetConfigSingleFile that you have mentioned both take two arguments whereas you are passing 4 arguments to the method. Are there any default arguments? If yes, can you please reproduce the original method declarations?
Most probably, the 4 argument overload of this method is expecting a String^% as the 2nd argument. This is what the compiler is suggesting anyway. But if we can have a look at the method declarations that could help diagnosing the problem.
This isn't an answer to my question, but worth being aware of - apparently there's a quirk in passing properties by reference.