<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>RBDevZone &#187; Tutorial</title>
	<atom:link href="http://www.rbdevzone.com/category/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rbdevzone.com</link>
	<description>The REALbasic Resource</description>
	<lastBuildDate>Tue, 31 Aug 2010 19:55:19 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>CallByName Function</title>
		<link>http://www.rbdevzone.com/2009/09/callbyname-function/</link>
		<comments>http://www.rbdevzone.com/2009/09/callbyname-function/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 18:45:21 +0000</pubDate>
		<dc:creator>Paul Lefebvre</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Source Code]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Visual Basic]]></category>
		<category><![CDATA[source]]></category>
		<category><![CDATA[VisualBasic]]></category>

		<guid isPermaLink="false">http://www.rbdevzone.com/?p=276</guid>
		<description><![CDATA[A post in the REAL Software forums asked if REALbasic has a CallByName function like VB has.  After reviewing my answer and the CallByName function in VB, I am presenting a more thorough solution here.
First, REALbasic does not have CallByName.  However, it does have Introspection (aka reflection) which can be used to achieve [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://forums.realsoftware.com/viewtopic.php?f=13&amp;t=29303">post</a> in the REAL Software forums asked if REALbasic has a CallByName function like VB has.  After reviewing my answer and the CallByName function in VB, I am presenting a more thorough solution here.</p>
<p>First, REALbasic does not have CallByName.  However, it does have Introspection (aka <a href="http://en.wikipedia.org/wiki/Reflection_(computer_science)">reflection</a>) which can be used to achieve this.</p>
<p>The official function definition in VB is:</p>

<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;">CallByName(<span style="color: #000080;">object</span> <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>, procname <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, calltype <span style="color: #000080;">As</span> <span style="color: #000080;">Integer</span>, [args() <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>])</pre></div></div>

<p>This is a bit limited as it cannot handle return values.  I&#8217;d also prefer a more object-oriented syntax.  So our REALbasic definitions are:</p>

<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Object</span>.CallByName(name <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, nameType <span style="color: #000080;">As</span> CallType, <span style="color: #000080;">ParamArray</span> args <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>)
<span style="color: #000080;">Object</span>.CallByName(name <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, nameType <span style="color: #000080;">As</span> CallType, <span style="color: #000080;">ParamArray</span> args <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span></pre></div></div>

<p>In order for this to be usable on any object, we&#8217;ll implement these as extension methods.  First we need to create a module to contain our methods.  Create a module called <strong>CallByNameExtension</strong>.  This self-contained module will eventually have everything we need to use CallByName in our projects.</p>
<p>Next, we need to create the CallType enumeration.  This is used to specify the type of the we want to call.  Our options are Method, PropertyGet and PropertySet.  On our module, create a CallType enumeration with those three values (Method, PropertyGet, PropertySet).</p>
<p>Now create our two method signatures for CallByName:</p>

<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Sub</span> CallByName(Extends obj <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>, name <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, nameType <span style="color: #000080;">As</span> CallType, <span style="color: #000080;">ParamArray</span> args <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>)
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Function</span> CallByName(Extends obj <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>, name <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, nameType <span style="color: #000080;">As</span> CallType, <span style="color: #000080;">ParamArray</span> args <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></pre></div></div>

<p>Since both of these methods will actually use very similar code, we will create a private worker method to actually do the call.  Create a new private method:</p>

<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Private</span> <span style="color: #000080;">Function</span> CallByNameWorker(obj <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>, name <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, nameType <span style="color: #000080;">As</span> CallType, args() <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></pre></div></div>

<p>Note that we&#8217;ve changed the ParamArray to just a simple array.  This is because we cannot resend the parameters as a ParamArray.</p>
<p>Let&#8217;s add the simple code to the public methods:</p>

<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Sub</span> CallByName(Extends obj <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>, name <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, nameType <span style="color: #000080;">As</span> CallType, <span style="color: #000080;">ParamArray</span> args <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>)
&nbsp;
   <span style="color: #000080;">Call</span> CallByNameWorker(obj, name, nameType, args)
&nbsp;
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Function</span> CallByName(Extends obj <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>, name <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, nameType <span style="color: #000080;">As</span> CallType, <span style="color: #000080;">ParamArray</span> args <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>
&nbsp;
  Return CallByNameWorker(obj, name, nameType, args)
&nbsp;
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></pre></div></div>

<p>As you can see, this code simply calls the worker, saving the return value if appropriate.  Since ParamArrays are converted to real arrays, we can just pass that along to the worker as well.</p>
<p>In the worker method we&#8217;ll use Introspection to actually call the method or to get/set the value of the property.  Here is the code:</p>

<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Private</span> <span style="color: #000080;">Function</span> CallByNameWorker(obj <span style="color: #000080;">As</span> <span style="color: #000080;">Object</span>, name <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>, nameType <span style="color: #000080;">As</span> CallType, args() <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>) <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>
  <span style="color: #000080;">If</span> obj &lt;&gt; Nil <span style="color: #000080;">Then</span>
&nbsp;
    <span style="color: #000080;">Dim</span> info <span style="color: #000080;">As</span> Introspection.TypeInfo
    info = Introspection.GetType(obj)
&nbsp;
    <span style="color: #000080;">Select</span> <span style="color: #000080;">Case</span> nameType
    <span style="color: #000080;">Case</span> CallType.Method
      // <span style="color: #000080;">Get</span> the names of all the methods <span style="color: #000080;">on</span> the <span style="color: #000080;">object</span>
      <span style="color: #000080;">Dim</span> methods() <span style="color: #000080;">As</span> Introspection.MethodInfo
      methods = info.GetMethods
&nbsp;
      // Search <span style="color: #000080;">for</span> the specified method
      <span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> m <span style="color: #000080;">As</span> Introspection.MethodInfo <span style="color: #000080;">In</span> methods
        <span style="color: #000080;">If</span> m.Name = name <span style="color: #000080;">Then</span>
          // We found it, so <span style="color: #000080;">call</span> it
          <span style="color: #000080;">Dim</span> rv <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>
          rv = m.Invoke(obj, args)
&nbsp;
          Return rv
        <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
      <span style="color: #000080;">Next</span>
&nbsp;
    <span style="color: #000080;">Case</span> CallType.PropertyGet
      // <span style="color: #000080;">Get</span> the names of all the properties <span style="color: #000080;">on</span> the <span style="color: #000080;">object</span>
      <span style="color: #000080;">Dim</span> props() <span style="color: #000080;">as</span> Introspection.PropertyInfo
      props = info.GetProperties
&nbsp;
      // Search <span style="color: #000080;">for</span> the specified <span style="color: #000080;">property</span>
      <span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> p <span style="color: #000080;">As</span> Introspection.PropertyInfo <span style="color: #000080;">In</span> props
        <span style="color: #000080;">If</span> p.Name = name <span style="color: #000080;">Then</span>
          // We found it, so return its value
          <span style="color: #000080;">Dim</span> value <span style="color: #000080;">As</span> <span style="color: #000080;">Variant</span>
          value = p.Value(obj)
&nbsp;
          Return value
        <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
      <span style="color: #000080;">Next</span>
&nbsp;
    <span style="color: #000080;">Case</span> CallType.PropertySet
      // <span style="color: #000080;">Get</span> the names of all the properties <span style="color: #000080;">on</span> the <span style="color: #000080;">object</span>
      <span style="color: #000080;">Dim</span> props() <span style="color: #000080;">as</span> Introspection.PropertyInfo
      props = info.GetProperties
&nbsp;
      // Search <span style="color: #000080;">for</span> the specified <span style="color: #000080;">property</span>
      <span style="color: #000080;">For</span> <span style="color: #000080;">Each</span> p <span style="color: #000080;">As</span> Introspection.PropertyInfo <span style="color: #000080;">In</span> props
        <span style="color: #000080;">If</span> p.Name = name <span style="color: #000080;">Then</span>
          // We found it so <span style="color: #000080;">set</span> its value <span style="color: #000080;">to</span> the first argument
          p.Value(obj) = args(0)
        <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
      <span style="color: #000080;">Next</span>
    <span style="color: #000080;">End</span> <span style="color: #000080;">Select</span>
&nbsp;
  <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
&nbsp;
Exception e <span style="color: #000080;">As</span> RuntimeException
  <span style="color: #000080;">Dim</span> eInfo <span style="color: #000080;">As</span> Introspection.TypeInfo
  eInfo = Introspection.GetType(e)
&nbsp;
  <span style="color: #000080;">Dim</span> eMessage <span style="color: #000080;">As</span> <span style="color: #000080;">String</span>
  eMessage = <span style="color: #800000;">&quot;A &quot;</span> + eInfo.FullName + <span style="color: #800000;">&quot; occurred.&quot;</span>
  <span style="color: #000080;">If</span> e.Message &lt;&gt; <span style="color: #800000;">&quot;&quot;</span> <span style="color: #000080;">Then</span>
    eMessage = eMessage + EndOfLine + <span style="color: #800000;">&quot;Message: &quot;</span> + e.Message
  <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
&nbsp;
  MsgBox(eMessage)
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span></pre></div></div>

<p>This code has one significant limitation when it comes to calling methods:  it cannot handle overloaded methods.  If you have multiple methods with the same name, but with different parameters, then this code will not always call the method you expect.  In order to fix this we would have to compare the types of each of the supplied arguments with the types of the arguments for each matching method and then call the one where everything matches.  This is all possible using Introspection, but I&#8217;ll leave it as an exercise for the reader.</p>
<p>Download the project with all the code: <a title="CallByName.rbp.zip" href="http://www.rbdevzone.com/wp-content/uploads/2009/09/CallByName.rbp.zip">CallByName.rbp.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rbdevzone.com/2009/09/callbyname-function/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
