<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; VBS: CallByName]]></title>
	<link rel="self" href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=13421&amp;type=atom" />
	<updated>2018-01-28T17:54:52Z</updated>
	<generator>PunBB</generator>
	<id>https://forum.script-coding.com/viewtopic.php?id=13421</id>
		<entry>
			<title type="html"><![CDATA[VBS: CallByName]]></title>
			<link rel="alternate" href="https://forum.script-coding.com/viewtopic.php?pid=123449#p123449" />
			<content type="html"><![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>]]></content>
			<author>
				<name><![CDATA[Xameleon]]></name>
				<uri>https://forum.script-coding.com/profile.php?id=8836</uri>
			</author>
			<updated>2018-01-28T17:54:52Z</updated>
			<id>https://forum.script-coding.com/viewtopic.php?pid=123449#p123449</id>
		</entry>
</feed>
