.NET generic classes and methods can be specialized to specific types in MAXScript by using Type.MakeGenericType
and MethodInfo.MakeGenericMethod()
. These .NET methods create a type-specific version of a type or method. For example, if you run:
callSiteOps = (dotNetClass "System.Runtime.CompilerServices.CallSiteOps")
showmethods callSiteOps
You will get:
.[static]AddRule <CallSite`1>site <T>rule
.[static]<T>Bind <System.Runtime.CompilerServices.CallSiteBinder>binder <CallSite`1>site <System.Object[]>args
.[static]ClearMatch <System.Runtime.CompilerServices.CallSite>site
.[static]<System.Runtime.CompilerServices.CallSite`1[T]>CreateMatchmaker <CallSite`1>site
.[static]<System.Boolean>Equals <System.Object>objA <System.Object>objB
.[static]<T[]>GetCachedRules <RuleCache`1>cache
.[static]<System.Boolean>GetMatch <System.Runtime.CompilerServices.CallSite>site
.[static]<System.Runtime.CompilerServices.RuleCache`1[T]>GetRuleCache <CallSite`1>site
.[static]<T[]>GetRules <CallSite`1>site
.[static]MoveRule <RuleCache`1>cache <T>rule <System.Int32>i
.[static]<System.Boolean>ReferenceEquals <System.Object>objA <System.Object>objB
.[static]<System.Boolean>SetNotMatched <System.Runtime.CompilerServices.CallSite>site
.[static]UpdateRules <CallSite`1>this <System.Int32>matched
true
As you can see from the output, the line \[static\]AddRule <CallSite`1>site <T>rule
indicates that the AddRule(<T>
) method is a generic method. If you wanted a MAXScript version of this method that works with System.String, you would first get the method as a dotNetObject, and then specialize it so that <T>
is System.String:
addRuleGeneric = getproperty callSiteOps "AddRule" asdotnetobject:true
addRuleStringType = addRuleGeneric.MakeGenericMethod #(dotNetClass "System.String")
The AddRule() method takes 2 arguments, an instance of a templated class 'CallSite' and an instance of the specialized class . Looking at the CallSite documentation, you will see the method is documented as
AddRule<T>(CallSite<T>, T)
Adds a rule to the cache maintained on the dynamic call site.
In the MAXScript showmethods output, note the first arg is listed as <CallSite`1>site
. This means that the argument is an instance of a generic class that is templated with a single Type (indicated by the `1 in the class name). Therefore in the documentation it is shown as CallSite<T>
.
If the generic class was templated with two Types, it would be '2. An example of a class templated with two Types is:
System.Collections.Generic.Dictionary<TKey,TValue>
Which in MAXScript looks like:
d = dotnetclass "System.Collections.Generic.Dictionary`2"
dotnet.showConstructors d
The showConstructors yields:
System.Collections.Generic.Dictionary`2()
System.Collections.Generic.Dictionary`2 <IDictionary`2>dictionary
System.Collections.Generic.Dictionary`2 <IEqualityComparer`1>comparer
System.Collections.Generic.Dictionary`2 <System.Int32>capacity
System.Collections.Generic.Dictionary`2 <System.Int32>capacity <IEqualityComparer`1>comparer
System.Collections.Generic.Dictionary`2 <IDictionary`2>dictionary <IEqualityComparer`1>comparer
By using the following code, you create a instance of a dictionary where TKey
is System.String and TValue
is System.Int32:
genericType = dotnet.GetType "System.Collections.Generic.Dictionary`2"
innerType1 = dotnet.GetType "System.String"
innerType2 = dotnet.GetType "int"
specificType = genericType.MakeGenericType #(innerType1, innerType2)
theDict = (dotnetclass "System.Activator").CreateInstance specificType
This calls constructor:
System.Collections.Generic.Dictionary`2()
This code:
theDict = (dotnetclass "System.Activator").CreateInstance specificType #(32)
Calls the constructor:
System.Collections.Generic.Dictionary`2 <System.Int32>capacity
If the constructor took more than one argument, the additional arguments would be specified as additional elements in the array.