串行端口读入扩展名因dotnet错误而失败

问题描述

我正在编写一个读取串行端口数据的扩展程序。我正在BC14 OnPremis上运行。 这就是我所拥有的。在客户端运行的全局变量(显然Serioal端口不在服务器上,带有事件,因为我需要以某种方式接收数据。

var
    [RunOnClient]
    [WithEvents]
    Port: DotNet SerialPortA;

当端口上的数据可用时调用的触发器。它实际上是被射击了。

trigger Port::DataReceived(sender: Variant; e: DotNet SerialDataReceivedEventArgs)
var
    CurrPort: DotNet SerialPortA;
    BarText: DotNet String;
begin
    CurrPort := sender;
    BarText := CurrPort.ReadLine();
    Message(BarText);
end;

在dotne.al文件中,我声明了SerialPort类型。由于某些原因,它将名称与其他名称混淆了,因此我必须添加一个后缀来键入别名。所以现在我的类型叫SerialPort A

assembly("System")
{
    Version = '4.0.0.0';
    Culture = 'neutral';
    PublicKeyToken = 'b77a5c561934e089';

    type("System.IO.Ports.SerialPort"; "SerialPortA") { }
    type("System.IO.Ports.SerialDataReceivedEventArgs"; "SerialDataReceivedEventArgs") { }
    type("System.IO.Ports.SerialErrorReceivedEventArgs"; "SerialErrorReceivedEventArgs") { }
}

问题是对CurrPort.ReadLine()调用失败,并显示以下错误

A call to System.Object.ReadLine Failed with this message: The type of one or more arguments does not match the method's parameter type.

我尝试使用另一种方法Read错误是相同的。它很可能与Nav将所有dotnet变量包装/解包为对象类型有关,但是我不知道该怎么做。猜猜这里出了什么问题吗?

事件日志中有一个错误说明

Server instance: N721
Category: Runtime
ClientSessionId: b6d2f654-0601-46b7-bd70-ae4fa637d422
ClientActivityId: 75ab980f-28d2-4a47-8d50-787c132c854c
ServerSessionUniqueId: cc752b06-1eab-43ed-8976-f1973da11ae5
ServerActivityId: fbc48c73-482c-4f84-87e3-4b3b1765dc5b
EventTime: 10/08/2020 06:29:21
Message   ObjectType: System.Object,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089
  MethodName: ReadLine
  BindingFlags: Instance,Public,InvokeMethod

ProcessId: 24200
Tag: 000010P
ThreadId: 199
Counter@R_487_4045@ion: 

还有一个

Server instance: N721
Category: Runtime
ClientSessionId: b6d2f654-0601-46b7-bd70-ae4fa637d422
ClientActivityId: 75ab980f-28d2-4a47-8d50-787c132c854c
ServerSessionUniqueId: cc752b06-1eab-43ed-8976-f1973da11ae5
ServerActivityId: fbc48c73-482c-4f84-87e3-4b3b1765dc5b
EventTime: 10/08/2020 06:29:21
Message (NavNCLDotNetInvokeException): This message had personal data removed. The original may still be in transient telemetry. Find it using the transientTelemetryId.
ParentException: NavNCLDotNetInvokeException
A call to System.Object.ReadLine Failed with this message: The type of one or more arguments does not match the method's parameter type.
ExceptionStackTrace:
   at Microsoft.Dynamics.Nav.Runtime.NavApplicationMethod.InvokeMethod(ITreeObject obj,String methodName,Object[] args,Boolean resolveHandler,Boolean throwOnNotFound)
   at Microsoft.Dynamics.Nav.Service.NSField.InvokeEventTriggerInternal(NavSession con,String eventName)
   at Microsoft.Dynamics.Nav.Service.NSField.InvokeEventTrigger(NavSession session,String eventName)
   at SyncInvokeInvokeEventTrigger(Object,Object[],Object[] )
   at System.ServiceModel.dispatcher.SyncmethodInvoker.Invoke(Object instance,Object[] inputs,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.RunInTransactionCombinator(ServiceOperation innerOperation,NSServiceBase serviceInstance,MethodBase syncmethod,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__displayClass28_1.<Combine>b__1(NSServiceBase serviceInstance,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.TransientErrorRetryCombinator(ServiceOperation innerOperation,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.ErrorMappingCombinator(ServiceOperation innerOperation,Object[]& outputs)
InnerException:
ParentException: TargetInvocationException
ExceptionStackTrace:
   at System.RuntimeMethodHandle.InvokeMethod(Object target,Object[] arguments,Signature sig,Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,Object[] parameters,Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,Binder binder,CultureInfo culture)
   at Microsoft.Dynamics.Nav.Runtime.NavApplicationMethod.InvokeMethod(ITreeObject obj,Boolean throwOnNotFound)
InnerException:
RootException: NavNCLDotNetInvokeException
A call to System.Object.ReadLine Failed with this message: The type of one or more arguments does not match the method's parameter type.
ExceptionStackTrace:
   at Microsoft.Dynamics.Nav.Types.NavAutomationHelper.getmethodInfo(String methodName,Type objectType,BindingFlags binding,ParameterModifier[] modifier,Type[] referenceTypes)
   at Microsoft.Dynamics.Nav.Runtime.NavDotNet.Invoke[T](String methodName,UInt32 methodindex,BindingFlags flags,ParameterModifier modifier,Type[] referenceTypes,Object[] arguments)
   at Microsoft.Dynamics.Nav.Runtime.NavDotNet.InvokeMethod[T](Boolean isstatic,Object[] arguments)
   at Microsoft.Dynamics.Nav.BusinessApplication.Page1057905.Porta58a58DataReceived_Scope.OnRun()
   at Microsoft.Dynamics.Nav.Runtime.NavMethodScope.Run()
   at Microsoft.Dynamics.Nav.BusinessApplication.Page1057905.Porta58a58DataReceived(NavVariant sender,NavDotNet e)
CallerStackTrace:
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.ErrorMappingCombinator(ServiceOperation innerOperation,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.PushPopCombinator(ServiceOperation innerOperation,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationTracer.TraceScopeCombinator(Category telemetryCategory,ServiceOperation innerOperation,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.<>c__displayClass10_0.<PerformanceCounterCombinator>b__0()
   at Microsoft.Dynamics.Nav.Runtime.NavPerformanceCounterSetter.UpdatePerformanceCountersWithAverageServiceOperationDuration(Stopwatch stopWatch,Action action)
   at Microsoft.Dynamics.Nav.Runtime.NavPerformanceCounterSetter.UpdatePerformanceCountersWithAverageServiceOperationAction(Action action,NavSession session)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.PerformanceCounterCombinator(ServiceOperation innerOperation,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.InitClientTelemetryIdsCombinator(ServiceOperation innerOperation,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.TlsClearCombinator(ServiceOperation innerOperation,Object[]& outputs)
   at Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.Invoke(Object instance,Object[]& outputs)
   at System.ServiceModel.dispatcher.dispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
   at System.ServiceModel.dispatcher.ImmutabledispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   at System.ServiceModel.dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
   at System.ServiceModel.dispatcher.MessageRpc.Wrapper.Resume(Boolean& alreadyResumednoLock)
   at System.ServiceModel.dispatcher.ThreadBehavior.ResumeProcessing(IResumeMessageRpc resume)
   at Microsoft.Dynamics.Nav.Runtime.NavSynchronizationContext.<>c__displayClass1_0.<ClearThreadLocalStorageDelegate>b__0(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state,Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.dispatch()


ProcessId: 24200
Tag: 00000HC
ThreadId: 199
Counter@R_487_4045@ion: 

解决方法

我没有要测试的串行端口,所以这是我的首要考虑。

您可能需要将变体转换为正确的类型:

trigger Port::DataReceived(sender: Variant; e: DotNet SerialDataReceivedEventArgs)
var
    Type: DotNet Type;
    Convert: DotNet Convert;
    CurrPort: DotNet SerialPortA;
    BarText: DotNet String;
begin
    // This check is just best pratice,but not needed in this case as we know sender is a SerialPort.
    if not sender.IsDotNet() then
      exit;

    Type := GetDotNetType(sender);
    CurrPort := Convert.ChangeType(sender,Type);
    BarText := CurrPort.ReadLine();
    Message(BarText);
end;