<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; VBS: CallByName]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=13421</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=13421&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «VBS: CallByName».]]></description>
		<lastBuildDate>Sun, 28 Jan 2018 17:54:52 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[VBS: CallByName]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=123449#p123449</link>
			<description><![CDATA[<p>Решил добавить сюда пример реализации функции <strong>CallByName</strong> для VBS.</p><div class="codebox"><pre><code>
Option Explicit

Const VbMethod	= 1
Const VbGet		= 2
Const VbLet		= 4
Const VbSet		= 8

RunInConsoleMode

&#039;Заготовка функции для теста
Function SomeFunction(a,b,c)
	WScript.Echo &quot;SomeFunction called&quot;
End Function

&#039;Заготовка класса со свойствами и методами для теста
Class clsTest
	Public Sub [@SomeMethod](a,b,c)
		WScript.Echo &quot;SomeMethod called&quot;
	End Sub
	
	Public Property Get PropertyGet(a,b,c)
		WScript.Echo &quot;Property Get called&quot;
		PropertyGet = a + b + c
	End Property
	
	Public Property Let PropertyLet(a,b)
		WScript.Echo &quot;Property Let called&quot;
	End Property
	
	Public Property Set PropertySet(a,b,c)
		WScript.Echo &quot;Property Set called&quot;
	End Property
	
	Public Default Sub DefaultMethod()
		WScript.Echo &quot;Default Method called&quot;
	End Sub
End Class

&#039;Создание тестового класс модуля для тестирования на его свойствах и методах
Dim objTest
Set objTest = New clsTest

With New VBSUDF
	
	&#039;Вызов функции
	.CallByName(Array(GetRef(&quot;SomeFunction&quot;),,,1,2,3))
	
	&#039;Вызов умолчательного метода у объекта 
	.CallByName(Array(objTest))

	&#039;Вызов метода по имени
	.CallByName(Array(objTest, &quot;@SomeMethod&quot;, vbMethod, 1,2,3))
	
	&#039;Получение свойства
	WScript.Echo &quot;Returned value: &quot; &amp; .CallByName(Array(objTest, &quot;PropertyGet&quot;, vbGet, 1,2,3))
	
	&#039;Присвоение свойства с типом вызова vbLet
	.CallByName(Array(objTest, &quot;PropertyLet&quot;, vbLet, 1,2))

	&#039;Присвоение свойства с типом вызова vbSet
	.CallByName(Array(objTest, &quot;PropertySet&quot;, vbSet, 1,2, CreateObject(&quot;Scripting.FileSystemObject&quot;)))
	
End With

WScript.Echo &quot;Script End. Press Enter to exit.&quot;
 
WScript.StdIn.ReadLine

Class VBSUDF
	Function CallByName(args)
		Dim i, Code, MethodName, CallType, lb, n, ErrDescription
		&#039;Определение границ массива
		lb = Lbound(args)
		n = Ubound(args)
		&#039;Получение параметров
		CallType = GetArrayItem(args,2) 
		MethodName = GetArrayItem(args,lb + 1)
		if InStr(1,MethodName,&quot;]&quot;) Then Err.Raise &amp;H800A0408, TypeName(Me)
		&#039;Если тип вызова не указан, то используется vbMethod по умолчанию
		if isEmpty(CallType) Then CallType = vbMethod
		&#039;Если тип вызова vbLet, vbSet, то перебор нужно вести до предпоследнего элемента,
		&#039;так как последний элемент будет присвоен через &quot;=&quot; 
		if CallType &gt; 2 Then n = n - 1
		&#039;Сборка строки аргументов
		For i = lb + 3 to n
			Code = Code &amp; &quot;,args(&quot; &amp; i &amp; &quot;)&quot;
		Next
		&#039;Добавка скобок 
		Code = &quot;(&quot; &amp; mid(Code,2) &amp; &quot;)&quot;
		&#039;Добавка имени метода в выражение
		if MethodName &lt;&gt; &quot;&quot; Then Code = &quot;.[&quot; &amp; MethodName &amp; &quot;]&quot; &amp;Code
		&#039;Определение типов вызова
		Select Case CallType
		Case vbGet, vbMethod
			Code = &quot;Stub args(lb)&quot; &amp; Code &amp; &quot;, CallByName&quot;
		Case vbLet, vbSet
			Code = &quot;args(lb)&quot; &amp; Code &amp; &quot; = args(n+1)&quot;
			if CallType = vbSet Then Code = &quot;Set &quot; &amp; Code
		Case Else
			Err.Raise vbObjectError + 1, TypeName(Me), &quot;Invalid call type&quot;
		End Select
		&#039;Выполнение построенного выражения
		On Error Resume Next
		Execute Code
		if Err.Number &lt;&gt; 0 Then
			ErrDescription = Err.Description
			On Error Goto 0
			Err.Raise vbObjectError + 1, TypeName(Me) &amp; &quot;.CallByName&quot;, ErrDescription &amp; &quot;. [&quot; &amp; MethodName &amp; &quot;]&quot;
		End if
	End Function
	
	&#039;Функция для получения элемента массива
	Private Function GetArrayItem(arr, i)
		if i &lt; Lbound(arr) or i &gt; Ubound(arr) Then Exit Function
		Stub arr(i), GetArrayItem
		if VarType(GetArrayItem) = vbError Then GetArrayItem = Empty
	End Function
	
	&#039;Заглушка для возврата данных при вызове Default метода объекта
	Private Sub Stub(paramIn, paramOut)
		&#039;Если на входе (в paramIn) объект, то используется Set, в ином случае прямое присвоение
		If isObject(paramIn) Then
			Set paramOut = paramIn
		Else
			paramOut = paramIn
		End If
	End Sub
End Class

&#039;Процедура для запуска в консольном режиме
Sub RunInConsoleMode()
	If InStr(1,WScript.FullName,&quot;cscript&quot;,1) &gt; 0 Then Exit Sub
	CreateObject(&quot;WScript.Shell&quot;).Run(&quot;cscript /nologo &quot;&quot;&quot; &amp; WScript.ScriptFullName &amp; &quot;&quot;&quot;&quot;)
	WScript.Quit
End Sub
</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Xameleon)]]></author>
			<pubDate>Sun, 28 Jan 2018 17:54:52 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=123449#p123449</guid>
		</item>
	</channel>
</rss>
