01-06-2010 01:44 PM - edited 01-06-2010 01:48 PM
Juergen -
The GetContstructorMetadataToken() method in my example assembly uses Type.GetConstructor() method to get a reference to the appropriate constructor. In particular, it uses the GetConstructor(Type[] types) implementation where types is an array that contains the Type of the parameters in the order in which the parameters appear in the Constructor prototype.
In my example, the Constructor prototype consists of a string parameter so I use the typeof(string) to get the string Type (System.String).
For the example you've provided for a constructor with the prototype MyClass(SequenceContext, string, int), you could create a Type array and pass it to the GetConstructor(Type[] types) method as shown below:
Type[] constructorParamInfo = new Type[3];
constructorParamInfo[0] = NationalInstruments.TestStand.Interop.API.SequenceContext;
constructorParamInfo[1] = System.String;
constructorParamInfo[2] = System.Int32;
myCnstrctrInfo = myAssemType.GetConstructor(constructorParamInfo);
Please Note that in order to use the NationalInstruments.TestStand.Interop.API.SequenceContext Type, you must reference the NationalInstruments.TestStand.Interop.API.dll assembly within the GetMetadataToken.dll assembly.
I hope this helps and answers your question.
01-06-2010 02:07 PM
Hi Mannoch,
Thanks for your answer. The solution you have pointed is well, i would done it in the same way as you, if i do it for only one constructor
But my question is how to make GetContructorMetadataToken(... Type[] myTypes) public to TestStand.
The aim is to make it multifunctional. Assume you like to use the function for many other constructors.
So it must controlled by TS. I do not know who to create a Type[] in TS, but i assume this is impossible.
Maybe a container could do it.
Juergen
01-06-2010 02:32 PM - edited 01-06-2010 02:36 PM
Juergen -
I understand what you are trying to do now. This is something that I originally attempted to implement in the example I provided. The best way of doing this would be through the use of an array of strings.
The GetConstructorMetadataToken() method would take an additional string[] parameter: GetConstructorMetadataToken(string assemPath, string fullClassName, string[] paramTypes)
From TestStand, you would pass an array of strings. So, you would call
GetConstructorMetadataToken(Locals.assemPath, Locals.fullClassName, Locals.paramArray)
where Locals.paramArray = {"SequenceContext", "string", "int"}
Then, within the GetConstructorMetadataToken() method, you could use Type.GetType(string typeName) as follows:
.
.
.
Type[] constructorParamInfo = new Type[paramTypes.Length];
for(int i = 0; i++; i < paramTypes.Length)
{
constructorParamInfo[i] = Type.GetType(paramTypes[i]);
}
myCnstrctrInfo = myAssemType.GetConstructor(constructorParamInfo);
.
.
.
I decided not to provide this exact implementation in my original example because it is possible that a Type may not be loaded in which case I believe the Type.GetType(paramTypes[i]) call will not execute correctly. For example, if the NationalInstruments.TestStand.Interop.API.dll assembly is not referenced in the GetMetadataToken.dll assembly, I don't think calling Type.GetType("SequenceContext") will properly execute.
This is why I made the following note in the post of my original example:
Note that the implementation of the GetMetaDataToken.dll that I've provided is very simplistic and specific to the example that I've created. Modifications will need to be made to make the implementation more robust and capable of handling the caveats I mentioned in the previous bullet. Also, you will have to update some of the hard-coded paths to match the paths on your machine.
Hope this helps.
01-06-2010 04:30 PM
Hi Mannoch,
You are right Type.GetType(string) is the trick.
for my example i have used instead a TS local a string[] to be independent of TS (so i can use it in some other code 🙂 )
public int GetConstructorMetadataToken(string assemPath, string fullClassName, string[] strArrayType)
{
ConstructorInfo myCnstrctrInfo;int metadataToken = -1;
Assembly myAssem = Assembly.LoadFrom(assemPath);Type[] types = myAssem.GetTypes();
Type myAssemType = myAssem.GetType(fullClassName);Type[] constructorParamInfo = new Type[strArrayType.Length];
for(int i=0; i < strArrayType.Length; i++){
constructorParamInfo[i] = Type.GetType(strArrayType[i]);}
myCnstrctrInfo = myAssemType.GetConstructor(constructorParamInfo);
metadataToken = myCnstrctrInfo.MetadataToken;
return metadataToken;}
To use SequenceContext you have to use the AssemblyQualifiedName
for TS4.0 it looks like that: "NationalInstruments.TestStand.Interop.API.SequenceContext, NationalInstruments.TestStand.Interop.API, Version=4.0.0.326, Culture=neutral, PublicKeyToken=ad9244eb3b825cd8"
Juergen
01-06-2010 04:38 PM
01-14-2010 04:25 AM
Hi Manooch,
I think I only need to have the MetadataToken of the Method to add parameters.
So I would like to transform your .Net method to Labwindows CVI because all my program is writted with CVI :
public int GetMethodMetadataToken(string assemPath, string fullClassName, string methodName) { MethodInfo myMthdInfo; int metadataToken = -1; Assembly myAssem = Assembly.LoadFrom(assemPath); Type myAssemType = myAssem.GetType("myTestAssembly.Class1"); myMthdInfo = myAssemType.GetMethod(methodName); metadataToken = myMthdInfo.MetadataToken; return metadataToken; }
So i get this in Labwindws CVI in including "mscorlib2.h":
long MetadataToken = 0; System_Reflection_Assembly ReflectionAssembly; CDotNetHandle ExceptionHandle; System_Type Type; System_Reflection_MethodInfo ReflectionMethodInfo; Initialize_mscorlib (); System_Reflection_Assembly_LoadFrom(sModulePath, &ReflectionAssembly, &ExceptionHandle); System_Reflection_Assembly_GetType_1(ReflectionAssembly,sClassName, &Type, &ExceptionHandle); System_Type_GetMethod_5 (Type,sFunctionName,&ReflectionMethodInfo,&ExceptionHandle); System_Reflection_MethodInfo_Get_MetadataToken(ReflectionMethodInfo,&MetadataToken, &ExceptionHandle); Close_mscorlib ();
But i get a FATAL RUN-TIME ERROR: The program has caused a 'General Protection' fault at 0023:004EFE37 on the function System_Reflection_MethodInfo_GetMetadataToken.
Have you got an idea what i do wrong?
Anthony
01-14-2010 09:14 AM
Anthony -
Ideally, you would have used the CVI .NET Controller to create a library of functions that map to the methods in the provided example assembly. I have never used the functions that you are attempting to use. Whether you continue down this path, or choose to create a .NET Controller in CVI, I recommend posting the question to the CVI forums as you will likely get more knowledgeable assistance there.
Hope this helps.
01-18-2010 09:01 AM
Hi Manooch_H
I'm investigating why my code which performed very well, doesn't work now!
So, I did some tests with several versions of TestStand and I don't get the same result!
When
I use the function TS_DotNetModuleLoadMemberInfo then the functions
getParametersList and getParametersCount, the results of these
functions are correct with TestStand 3.5 and 4.0. There is no problem with my code and these versions of TestStand!
From TestStand 4.0, it doesn't work then it's the same code! So I guess it is a regression? (even if the function TS_DotNetModuleLoadMemberInfo is declared deprecated )
I also did a test with version 3.0 and then the function returns TS_DotNetModuleLoadMemberInfo error -17,500 Unknow Error.
Can you tell me more about these issues?
Anthony
01-20-2010 09:27 AM
Anthony -
I'm confused. You say that LoadMemberInfo() works for TestStand 3.5 and TestStand 4.0. But then you claim that it doesn't work from TestStand 4.0 and on. Which is it? Does the code work in TestStand 4.0 or not?
I've tested the LoadMemberInfo() method in TestStand 4.0 and it doesn't behave as expected. If you have a working example of using LoadMemberInfo() in TestStand 4.0, could you post it to this thread? I would be happy to look over it.
01-20-2010 09:41 AM - edited 01-20-2010 09:42 AM