How to construct Generic Net types using InvokeOverload fn.

Using (or providing) Microsoft.NET Classes

How to construct Generic Net types using InvokeOverload fn.

Postby RossHale on Wed Jan 26, 2011 1:30 am

In Getting Started - Frequently Asked Questions (FAQ) section of the Forums,
John Daintree posted -
"How do I force a call to a specific .Net function overload?"

He included a function InvokeOverload that allowed you to select
a method or constructor by specifying a .NET type, method name and list of types for desired overload. Constructors all have the name '.ctor'

InvokeOverload can be used to construct type instances from text names -
Code: Select all
'System.DateTime' InvokeOverload '.ctor' (3⍴Int32)(1999 10 31)
31-Oct-99 12:00:00 AM


You can also construct Generic types by giving the "Mangled" text name.
List<System.DateTime> is mangled to
'System.Collections.Generic.List`1[System.DateTime]'

Dictionary<System.String,System.DateTime> is mangled to
'System.Collections.Generic.Dictionary`2[System.String,System.DateTime]'

The mangled name is composed by replacing < with [ and > with ]
and preceding that with a back-tick (`) and the number of Generic types.
Code: Select all
     dt←'System.Collections.Generic.Dictionary`2[System.String,System.DateTime]'
     mydictionary←dt InvokeOverLoad '.ctor' ⍬ ⍬
     mydictionary.Count ⍝ empty
0


My setup is Dyalog 12.1 Unicode 32-bit on Windows 7 Professional 64-bit
with .NET Framework version 4.0.
I have ⎕using specified in some detail to cover the various assemblies
covered by .Net namespace System.Collections.Generic.
I use ⎕io←0 to match 0 based indexing for .Net collections
and ⎕ML←1. I modified InvokeOverLoad slightly to select null constructors.

I also made up a static or shared APL class Kind to provide a simple
automatic mangling and slightly different syntax ..

Code: Select all
      dz←Kind.New 'System.Collections.Generic.Dictionary<System.String,System.DateTime>' ⍬ ⍬
      dz
System.Collections.Generic.Dictionary`2[System.String,System.DateTime]


Ross Hale

Code: Select all
     ↑⎕using
                                                                                               
System,C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll                               
System,C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll                                 
System.Collections,C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll                   
System.Reflection,C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll                   
System.Reflection.Cache,C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll             
System.Reflection.Emit,C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll               
System.Collections.Generic,C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll           
System.Collections.Generic,C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll             
System.Collections.Generic,C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Core.dll       
System.Collections.Generic,C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.ServiceModel.dll

⍝ includes lead '' to allow fully qualified names.



Code: Select all
r←obj InvokeOverload(name types args);fns;params;overload;flags
 ⍝⍝ Ross Hale -- slight modifications to allow fully qualify names
 ⍝⍝ such as System.Type instead of Type ..
 ⍝⍝ only interested in public instance
 flags←System.Reflection.BindingFlags.Public+System.Reflection.BindingFlags.Instance 
 :If name≡'.ctor' ⍝ invoking []NEW?
     fns←(System.Type.GetType⊂obj).GetConstructors flags ⍝ find all fns with name
     args←,⊂args
 :Else ⍝ and instance as an argument
     fns←obj.GetType.FindMembers MemberTypes.Method flags System.Type.FilterName name ⍝ find named methods
     args←obj args ⍝ arguments include instance
 :EndIf
 ⍝ find all parameter lists
 params←{0::⍬ ⋄ ⍵.ParameterType}¨fns.GetParameters 
 :If 0=⍴,types
     overload←(0=∊⍴¨params)/fns ⍝ select overload with no parameters
 :Else
     overload←((⊂,types)≡¨params)/fns ⍝ and find correct overload
 :EndIf
 :If 1=⍴overload ⍝ find one?
     r←(⊃overload).Invoke args ⍝ invoke the function
 :EndIf


Code: Select all
:Class Kind

    ∇ r←New(obj types args)
      :Access Public Shared
      r←(Mangle obj)InvokeOverload'.ctor'types args
    ∇

    ∇ r←Mangle obj;j;k;n;typelist;mark
      :Access Public Shared
    ⍝ if obj is a string specifying a Generic .NET type such as Dictionary<System.String,System.Int32>
    ⍝ return mangled .NET name such as Dictionary`2[System.String,System.Int32]
      r←obj
      j k←r⍳'<>'
      :If j<k
          n←1+','+.=typelist←((∨\r='<')∧(⌽∨\⌽r='>'))/r ⍝ number of Generic typenames enclosed in <>
          mark←(∧\r≠'<')/r
          mark,←'`',(⍕n),'[',(1↓¯1↓typelist),']'
          mark,←(⌽∧\⌽r≠'>')/r
          r←mark
      :EndIf
    ∇

    ∇ r←obj InvokeOverload(name types args);fns;params;overload;flags;⎕ML
      :Access Public Shared
      ⎕ML←1
 ⍝⍝ Ross Hale -- slight modifications to fully qualify names such as System.Type instead of Type ..
 ⍝⍝ only interested in public instance

      flags←System.Reflection.BindingFlags.Public+System.Reflection.BindingFlags.Instance       
      :If name≡'.ctor' ⍝ invoking []NEW?
          fns←(System.Type.GetType⊂obj).GetConstructors flags ⍝ find all fns with name
          args←,⊂args
      :Else ⍝ and instance as an argument
          fns←obj.GetType.FindMembers MemberTypes.Method flags System.Type.FilterName name ⍝ find named methods
          args←obj args ⍝ arguments include instance
      :EndIf
      params←{0::⍬ ⋄ ⍵.ParameterType}¨fns.GetParameters ⍝ find all parameter lists
      :If 0=⍴,types  ⍝⍝ Ross Hale
          overload←(0=∊⍴¨params)/fns ⍝ select overload with no parameters  ⍝ (⎕ML≥1) ∊ is Enlist or unravel
      :Else
          overload←((⊂,types)≡¨params)/fns ⍝ and find correct overload
      :EndIf
      :If 1=⍴overload ⍝ find one?
          r←(⊃overload).Invoke args ⍝ invoke the function
      :EndIf
    ∇

:EndClass
User avatar
RossHale
 
Posts: 31
Joined: Thu Jun 18, 2009 9:08 pm
Location: Bellevue, Washington, USA

Return to Microsoft.NET

Who is online

Users browsing this forum: No registered users and 1 guest