Page 1 of 2

Pass repository item as parameter to user code

Posted: Thu Jul 11, 2013 10:35 am
by reiniuny
How is it possible to pass a repository item as parameter to a user code method?

As I see I just can pass strings to user code methods. If I define an other class then string as data type for parameter the user code function doesn't appear in the combobox.

Re: Pass repository item as parameter to user code

Posted: Thu Jul 11, 2013 1:19 pm
by krstcs
Currently you can only pass strings to user code.

I have requested that they add the ability to pass other types besides strings (including repository items). It may be a while before that happens though, if it ever does.

Re: Pass repository item as parameter to user code

Posted: Thu Jul 11, 2013 5:08 pm
by sergii
Just an idea: Why you cannot pass unique XPath to the repository item and catch it on other end using code:

Code: Select all

var xpath = string.Format("/dom[@domain='"+ EnvLinks.RAMlink +"']/.//a[@innertext~'.*{0}.*{1}']/../../../div[5]/div", LastName, FirstName);
DivTag elem = null;
Host.Local.TryFindSingle(xpath, out elem);
elem with contain your repository item of type Div.
I didn't find a way to make it universal for any type of repository item, but this implementation works quite good for me.

Re: Pass repository item as parameter to user code

Posted: Thu Jul 11, 2013 7:06 pm
by krstcs
The problem with that approach is that you still have to know ahead of time what the XPath is you need. And you will have to hard-code it somewhere, either in the module or in the data. You can't pass the XPath straight from a repository object in a module without getting into user code.

I would like to be able to fully de-couple the repository objects from my code modules.

If they allow us to pass repository objects then we could change the XPath in the repository and be done with it. This would also allow us to make more generic methods that could be used on any repository object.

Re: Pass repository item as parameter to user code

Posted: Fri Jul 12, 2013 6:16 am
by reiniuny
The approach krstcs explained was my intent too.

At the moment I've created a repository item using a variable. Before calling the user function I set the variable to the desired value. But this value I've to hardcode on many places, so if the value changes I've to change it many times.

Instead of that I'd like to use a repository item and pass it to the user code, then I just would have to change the value once if it changes.

Re: Pass repository item as parameter to user code

Posted: Fri Aug 30, 2013 2:57 pm
by kmck
Being able to pass the repository item to a method via a parameter would be a very helpful addition. I've had the same issue as posters above where I have had to use an xpath passed as a parameter, but this unfortunately makes for fragile code. If the xpath changes on a repository item, you can change the repo item's path and have it automatically update everywhere where that item is called, whereas using an xpath means having to manually go through the code, find the defunct xpaths and change each one by hand should they no longer point to the correct item.

Is there still currently no workaround for this?

Re: Pass repository item as parameter to user code

Posted: Tue Sep 03, 2013 12:25 pm
by Support Team
Hello,

Currently, it's not possible to pass a repository item to a user code action.
A possible workaround in Ranorex 4.1 might be to navigate through repository items using the Children property of the RepoItemInfo class. Please take a look at the code snippet below:
public void GetRepoItems()
{
	var items = repo.VipApp.SelfInfo.Children;
	foreach (var item in items)
	{
		Report.Info(item.ToString());
	}		
}
Regards,
Markus (T)

Re: Pass repository item as parameter to user code

Posted: Thu Nov 14, 2013 1:40 pm
by odklizec
Hi, sorry for hijacking this thread, but I have a similar problem and I thought about solving it by using string parameter and InvokeMethod.

Basically, I have a recording with the User Code, which uses two string parameters containing the rxPath.
I thought about replacing the hardcoded string parameter (containing the rxpath), with somewhat more flexible Repository.ItemInfo.Path string. Such string (passed via string parameter to user code) does not automatically expand to repository path, because after passing as a sting, it behaves like a string ;) But I found something about InvokeMethod and I think this method should be a way to call the string-based method? Then only problem is, that I'm not quite sure how to implement it (sorry, I'm still a C# noob). Any idea?

Here is how my recording looks like:
RepoItemParam.png
Now the question is, how to use the InvokeMethod to call "repo.LiteBox3d.SceneInitializedInfo.Path" passed via string parameter and get the expanded path? Any idea? I'm sure the string needs to be split. That's the easy part. So let's assume the parameter is already split. How to use the InvokeMethod? Any idea? Thank you in advance!

Re: Pass repository item as parameter to user code

Posted: Mon Nov 18, 2013 5:37 pm
by Support Team
Hello odklizec,

We provide our InvokeMethod for Ranorex Controls to invoke a specified method on a control as described in our API. In your case, you would need to use .NET Reflection to pass your objects to a User Code method.
Please note that only string objects could be passed from the Recording's actions table to a method.

This article on MSDN describes the usage of MethodBase.InvokeMethod and gives a short example:
http://msdn.microsoft.com/de-de/library ... .110).aspx

On the base of this example I created the following method to pass the RepoItemInfo object to my method using Reflection. Please take a look at it.
public void ReflectionCall() {
	Type myClass = this.GetType();
	var repo = <YourRepository>.Instance;
	var txtBox = repo.FormVipApplication.FirstNameInfo;

	MethodInfo myMethod = myClass.GetMethod("HelloWorld");
	object magicValue = myMethod.Invoke(this, new object[]{txtBox});
}

public void HelloWorld(RepoItemInfo infoObject) {
	Report.Info("Path of RepoItemInfo object: " + infoObject.AbsolutePath);
}
In this way, you could pass any object that you want to your User Code method.
Please let me know if this helped you.

Regards,
Markus (T)

Re: Pass repository item as parameter to user code

Posted: Tue Nov 19, 2013 9:53 am
by odklizec
Hi Markus,

Thank you for the example! It looks exactly what I'm looking for. I will give it a try and let you know. Thanks again!

Re: Pass repository item as parameter to user code

Posted: Tue Dec 17, 2013 2:00 pm
by odklizec
Hi Markus,

After some time, I was finally able to return to this problem and I'm afraid, I'm unable to modify your nice sample to achieve my goal.

Here is what I have:
public void Wait_For_Not_Exists(string repoElement)
{
// where repoElement contains string like repo.LiteBox3d.SceneInitializedInfo
    Type myClass = this.GetType();  

    MethodInfo myMethod = myClass.GetMethod("????");  //what should be here if I don't want to use another method, like in your sample?
    object magicValue = myMethod.Invoke(this, new object[]{repoElement});  
    string repoPath = magicValue.AbsolutePath;  //this obviously doesn't work because: 'object' does not contain a definition for 'AbsolutePath' and no extension method 'AbsolutePath' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
    System.Diagnostics.Debug.WriteLine("repoPath: " + repoPath);
}
Any idea how to change the code to make it working (to change repoElement string to repo object)? Thank you for your kind help!

Re: Pass repository item as parameter to user code

Posted: Thu Dec 19, 2013 4:34 pm
by Support Team
Hello odklizec,

Your assumption is correct. You would need to use a RepoItemInfo object to work with your example.
A string value with the path to the object is not enough, unfortunately. You could of course change the object type that is passed to your method (e.g. to a RepoItem).

Hint: The following method will get the element based on the path:
// find your element based on your path
var txtBox = Host.Local.FindSingle<Ranorex.Text>(repoElement);
In order to call a method using GetMethod(), you would need to know the method name.
In my example, I created a method HelloWorld() for that purpose.

Regards,
Markus (T)

Re: Pass repository item as parameter to user code

Posted: Fri Dec 20, 2013 9:35 am
by odklizec
Hi Markus

Thanks for your explanation and a new hint.

In previous version of my code, I passed the repo paths (via parameters). But these "path strings" parameters used to be too long and not resistant to repository path changes. So my idea is to pass the repo item names (instead of paths) and then somehow "convert" the string parameters back to repository items, which are usable in code.

I'm currently using TryFindSingle in this way:
Host.Local.TryFindSingle(repo.LiteBox3d.SceneInitializedInfo.AbsolutePath, out element);

But I consider this way hardcoded and not very flexible. I would rather like to have a method, to which I pass the repo element names (not paths) via string parameters.

OK, I will try to use your "HelloWorld" method approach ;) Thanks again!

Re: Pass repository item as parameter to user code

Posted: Fri Dec 20, 2013 10:32 am
by odklizec
OK, I tried your sample including the "HelloWorld" sample method and I'm afraid, I'm still unable to achieve what I want.

The problem is, in this line:
var txtBox = repo.FormVipApplication.FirstNameInfo;
Basically, I need txtBox to hold a string variable (passed to user code via string parameter)
Here is the edited sample code...
public void ReflectionCall(string repoElement) {  
        Type myClass = this.GetType();  
//        var txtBox = repo.FormVipApplication.FirstNameInfo;  // your original line  
           var txtBox = repoElement;  //repo element passed by string param  e.g. "repo.LiteBox3d.LoadingDoneInfo"

        MethodInfo myMethod = myClass.GetMethod("HelloWorld");  
        object magicValue = myMethod.Invoke(this, new object[]{txtBox});  
    }  
      
    public void HelloWorld(RepoItemInfo infoObject) {  
        Report.Info("Path of RepoItemInfo object: " + infoObject.AbsolutePath);  
    }

Re: Pass repository item as parameter to user code

Posted: Fri Dec 20, 2013 2:45 pm
by krstcs
Add the "Path" attribute:

var txtBox = repo.FormVipApplication.FirstNameInfo.Path;