mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-07-04 12:48:17 +00:00
Allow overloads of the same function
It is now possible to define multiple overloads of the same function, each with different parameters. This is extremely useful for maintaining backwards compatibility in the face of the changes between GL 4.3 and 4.4.
This commit is contained in:
parent
60f971ffed
commit
9789225e0c
|
@ -205,14 +205,22 @@ namespace Bind
|
||||||
sw.WriteLine("{");
|
sw.WriteLine("{");
|
||||||
sw.Indent();
|
sw.Indent();
|
||||||
|
|
||||||
foreach (Delegate d in delegates.Values)
|
foreach (var overloads in delegates.Values)
|
||||||
{
|
{
|
||||||
|
int overload_count = -1;
|
||||||
|
foreach (var d in overloads)
|
||||||
|
{
|
||||||
|
overload_count++;
|
||||||
|
string overload_suffix = overload_count > 0 ? overload_count.ToString() : String.Empty;
|
||||||
|
d.Name += overload_suffix;
|
||||||
|
|
||||||
sw.WriteLine("[System.Security.SuppressUnmanagedCodeSecurity()]");
|
sw.WriteLine("[System.Security.SuppressUnmanagedCodeSecurity()]");
|
||||||
sw.WriteLine("internal {0};", GetDeclarationString(d, true));
|
sw.WriteLine("internal {0};", GetDeclarationString(d, true));
|
||||||
sw.WriteLine("internal {0}static {1} {2}{1};", // = null
|
sw.WriteLine("internal {0}static {2} {1}{2};", // = null
|
||||||
d.Unsafe ? "unsafe " : "",
|
d.Unsafe ? "unsafe " : "",
|
||||||
d.Name,
|
Settings.FunctionPrefix,
|
||||||
Settings.FunctionPrefix);
|
d.Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sw.Unindent();
|
sw.Unindent();
|
||||||
|
@ -243,15 +251,15 @@ namespace Bind
|
||||||
sw.Indent();
|
sw.Indent();
|
||||||
//sw.WriteLine("static {0}() {1} {2}", Settings.ImportsClass, "{", "}"); // Disable BeforeFieldInit
|
//sw.WriteLine("static {0}() {1} {2}", Settings.ImportsClass, "{", "}"); // Disable BeforeFieldInit
|
||||||
sw.WriteLine();
|
sw.WriteLine();
|
||||||
foreach (Delegate d in delegates.Values)
|
foreach (Delegate d in delegates.Values.SelectMany(v => v))
|
||||||
{
|
{
|
||||||
sw.WriteLine("[System.Security.SuppressUnmanagedCodeSecurity()]");
|
sw.WriteLine("[System.Security.SuppressUnmanagedCodeSecurity()]");
|
||||||
sw.WriteLine(
|
sw.WriteLine(
|
||||||
"[System.Runtime.InteropServices.DllImport({0}.Library, EntryPoint = \"{1}{2}\"{3})]",
|
"[System.Runtime.InteropServices.DllImport({0}.Library, EntryPoint = \"{1}{2}\"{3})]",
|
||||||
Settings.OutputClass,
|
Settings.OutputClass,
|
||||||
Settings.FunctionPrefix,
|
Settings.FunctionPrefix,
|
||||||
d.Name,
|
d.EntryPoint,
|
||||||
d.Name.EndsWith("W") || d.Name.EndsWith("A") ? ", CharSet = CharSet.Auto" : ", ExactSpelling = true"
|
d.EntryPoint.EndsWith("W") || d.EntryPoint.EndsWith("A") ? ", CharSet = CharSet.Auto" : ", ExactSpelling = true"
|
||||||
);
|
);
|
||||||
sw.WriteLine("internal extern static {0};", GetDeclarationString(d, false));
|
sw.WriteLine("internal extern static {0};", GetDeclarationString(d, false));
|
||||||
}
|
}
|
||||||
|
@ -346,7 +354,7 @@ namespace Bind
|
||||||
}
|
}
|
||||||
|
|
||||||
sw.WriteLine("[AutoGenerated(Category = \"{0}\", Version = \"{1}\", EntryPoint = \"{2}\")]",
|
sw.WriteLine("[AutoGenerated(Category = \"{0}\", Version = \"{1}\", EntryPoint = \"{2}\")]",
|
||||||
f.Category, f.Version, Settings.FunctionPrefix + f.WrappedDelegate.Name);
|
f.Category, f.Version, Settings.FunctionPrefix + f.WrappedDelegate.EntryPoint);
|
||||||
sw.WriteLine("public static ");
|
sw.WriteLine("public static ");
|
||||||
sw.Write(GetDeclarationString(f));
|
sw.Write(GetDeclarationString(f));
|
||||||
sw.WriteLine();
|
sw.WriteLine();
|
||||||
|
@ -915,8 +923,6 @@ namespace Bind
|
||||||
|
|
||||||
string GetDeclarationString(Parameter p, bool override_unsafe_setting)
|
string GetDeclarationString(Parameter p, bool override_unsafe_setting)
|
||||||
{
|
{
|
||||||
bool unsafe_allowed = override_unsafe_setting;
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
if (p.Flow == FlowDirection.Out)
|
if (p.Flow == FlowDirection.Out)
|
||||||
|
|
|
@ -69,21 +69,27 @@ namespace Bind
|
||||||
{
|
{
|
||||||
Console.WriteLine("Processing delegates.");
|
Console.WriteLine("Processing delegates.");
|
||||||
var nav = new XPathDocument(Overrides).CreateNavigator();
|
var nav = new XPathDocument(Overrides).CreateNavigator();
|
||||||
foreach (var d in delegates.Values)
|
foreach (var overloads in delegates.Values)
|
||||||
|
{
|
||||||
|
foreach (var d in overloads)
|
||||||
{
|
{
|
||||||
TranslateExtension(d);
|
TranslateExtension(d);
|
||||||
TranslateReturnType(enum_processor, nav, d, enums, apiname);
|
TranslateReturnType(enum_processor, nav, d, enums, apiname);
|
||||||
TranslateParameters(enum_processor, nav, d, enums, apiname);
|
TranslateParameters(enum_processor, nav, d, enums, apiname);
|
||||||
TranslateAttributes(nav, d, enums, apiname);
|
TranslateAttributes(nav, d, enums, apiname);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Console.WriteLine("Generating wrappers.");
|
Console.WriteLine("Generating wrappers.");
|
||||||
var wrappers = CreateWrappers(delegates, enums);
|
var wrappers = CreateWrappers(delegates, enums);
|
||||||
|
|
||||||
Console.WriteLine("Creating CLS compliant overloads.");
|
Console.WriteLine("Creating CLS compliant overloads.");
|
||||||
wrappers = CreateCLSCompliantWrappers(wrappers, enums);
|
wrappers = CreateCLSCompliantWrappers(wrappers, enums);
|
||||||
Console.WriteLine("Removing non-CLS compliant duplicates.");
|
|
||||||
|
|
||||||
return MarkCLSCompliance(wrappers);
|
Console.WriteLine("Removing non-CLS compliant duplicates.");
|
||||||
|
wrappers = MarkCLSCompliance(wrappers);
|
||||||
|
|
||||||
|
return wrappers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetOverridesPath(string apiname, string function, string extension)
|
public static string GetOverridesPath(string apiname, string function, string extension)
|
||||||
|
@ -132,6 +138,8 @@ namespace Bind
|
||||||
// Translate enum types
|
// Translate enum types
|
||||||
if (normal && @enum.Name != "GLenum" && @enum.Name != "Boolean")
|
if (normal && @enum.Name != "GLenum" && @enum.Name != "Boolean")
|
||||||
{
|
{
|
||||||
|
type.IsEnum = true;
|
||||||
|
|
||||||
if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) != Settings.Legacy.None)
|
if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) != Settings.Legacy.None)
|
||||||
{
|
{
|
||||||
type.QualifiedType = "int";
|
type.QualifiedType = "int";
|
||||||
|
@ -146,6 +154,8 @@ namespace Bind
|
||||||
}
|
}
|
||||||
else if (Generator.GLTypes.TryGetValue(type.CurrentType, out s))
|
else if (Generator.GLTypes.TryGetValue(type.CurrentType, out s))
|
||||||
{
|
{
|
||||||
|
type.IsEnum = true;
|
||||||
|
|
||||||
// Check if the parameter is a generic GLenum. If it is, search for a better match,
|
// Check if the parameter is a generic GLenum. If it is, search for a better match,
|
||||||
// otherwise fallback to Settings.CompleteEnumName (named 'All' by default).
|
// otherwise fallback to Settings.CompleteEnumName (named 'All' by default).
|
||||||
if (s.Contains("GLenum") /*&& !String.IsNullOrEmpty(category)*/)
|
if (s.Contains("GLenum") /*&& !String.IsNullOrEmpty(category)*/)
|
||||||
|
@ -157,7 +167,9 @@ namespace Bind
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Better match: enum.Name == function.Category (e.g. GL_VERSION_1_1 etc)
|
// Better match: enum.Name == function.Category (e.g. GL_VERSION_1_1 etc)
|
||||||
if (enums.ContainsKey(category))
|
// Note: for backwards compatibility we use "category" only for the gl api.
|
||||||
|
// glcore, gles1 and gles2 use the All enum instead.
|
||||||
|
if (apiname == "gl" && enums.ContainsKey(category))
|
||||||
{
|
{
|
||||||
type.QualifiedType = String.Format("{0}{1}{2}", Settings.EnumsOutput,
|
type.QualifiedType = String.Format("{0}{1}{2}", Settings.EnumsOutput,
|
||||||
Settings.NamespaceSeparator, enum_processor.TranslateEnumName(category));
|
Settings.NamespaceSeparator, enum_processor.TranslateEnumName(category));
|
||||||
|
@ -486,7 +498,7 @@ namespace Bind
|
||||||
FunctionCollection CreateWrappers(DelegateCollection delegates, EnumCollection enums)
|
FunctionCollection CreateWrappers(DelegateCollection delegates, EnumCollection enums)
|
||||||
{
|
{
|
||||||
var wrappers = new FunctionCollection();
|
var wrappers = new FunctionCollection();
|
||||||
foreach (var d in delegates.Values)
|
foreach (var d in delegates.Values.SelectMany(v => v))
|
||||||
{
|
{
|
||||||
wrappers.AddRange(CreateNormalWrappers(d, enums));
|
wrappers.AddRange(CreateNormalWrappers(d, enums));
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,6 @@ namespace Bind.Structures
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class Constant : IComparable<Constant>
|
class Constant : IComparable<Constant>
|
||||||
{
|
{
|
||||||
static StringBuilder translator = new StringBuilder();
|
|
||||||
|
|
||||||
#region PreviousName
|
#region PreviousName
|
||||||
|
|
||||||
string original_name;
|
string original_name;
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace Bind.Structures
|
||||||
//this.Version = !String.IsNullOrEmpty(d.Version) ? new string(d.Version.ToCharArray()) : "";
|
//this.Version = !String.IsNullOrEmpty(d.Version) ? new string(d.Version.ToCharArray()) : "";
|
||||||
Deprecated = d.Deprecated;
|
Deprecated = d.Deprecated;
|
||||||
DeprecatedVersion = d.DeprecatedVersion;
|
DeprecatedVersion = d.DeprecatedVersion;
|
||||||
|
EntryPoint = d.EntryPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -237,6 +238,7 @@ namespace Bind.Structures
|
||||||
|
|
||||||
public bool Deprecated { get; set; }
|
public bool Deprecated { get; set; }
|
||||||
public string DeprecatedVersion { get; set; }
|
public string DeprecatedVersion { get; set; }
|
||||||
|
public string EntryPoint { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -261,7 +263,12 @@ namespace Bind.Structures
|
||||||
|
|
||||||
public int CompareTo(Delegate other)
|
public int CompareTo(Delegate other)
|
||||||
{
|
{
|
||||||
return Name.CompareTo(other.Name);
|
int ret = Name.CompareTo(other.Name);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = Parameters.CompareTo(other.Parameters);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = ReturnType.CompareTo(other.ReturnType);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -270,21 +277,34 @@ namespace Bind.Structures
|
||||||
|
|
||||||
public bool Equals(Delegate other)
|
public bool Equals(Delegate other)
|
||||||
{
|
{
|
||||||
return CompareTo(other) == 0;
|
return
|
||||||
|
Name.Equals(other.Name) &&
|
||||||
|
Parameters.Equals(other.Parameters) &&
|
||||||
|
ReturnType.Equals(other.ReturnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
#region class DelegateCollection : SortedDictionary<string, Delegate>
|
#region DelegateCollection
|
||||||
|
|
||||||
class DelegateCollection : SortedDictionary<string, Delegate>
|
class DelegateCollection : IDictionary<string, List<Delegate>>
|
||||||
{
|
{
|
||||||
|
readonly SortedDictionary<string, List<Delegate>> Delegates =
|
||||||
|
new SortedDictionary<string, List<Delegate>>();
|
||||||
|
|
||||||
public void Add(Delegate d)
|
public void Add(Delegate d)
|
||||||
{
|
{
|
||||||
if (!ContainsKey(d.Name))
|
if (!ContainsKey(d.Name))
|
||||||
{
|
{
|
||||||
Add(d.Name, d);
|
Add(d.Name, new List<Delegate> { d });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var list = Delegates[d.Name];
|
||||||
|
if (!list.Contains(d))
|
||||||
|
{
|
||||||
|
list.Add(d);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -295,5 +315,121 @@ namespace Bind.Structures
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IDictionary Members
|
||||||
|
|
||||||
|
public void Add(string key, List<Delegate> value)
|
||||||
|
{
|
||||||
|
Delegates.Add(key, value.ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsKey(string key)
|
||||||
|
{
|
||||||
|
return Delegates.ContainsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(string key)
|
||||||
|
{
|
||||||
|
return Delegates.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue(string key, out List<Delegate> value)
|
||||||
|
{
|
||||||
|
return Delegates.TryGetValue(key, out value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Delegate> this[string index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Delegates[index];
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Delegates[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICollection<string> Keys
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Delegates.Keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICollection<List<Delegate>> Values
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Delegates.Values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ICollection implementation
|
||||||
|
|
||||||
|
public void Add(KeyValuePair<string, List<Delegate>> item)
|
||||||
|
{
|
||||||
|
Delegates.Add(item.Key, item.Value.ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
Delegates.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(KeyValuePair<string, List<Delegate>> item)
|
||||||
|
{
|
||||||
|
return Delegates.Contains(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(KeyValuePair<string, List<Delegate>>[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
Delegates.CopyTo(array, arrayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(KeyValuePair<string, List<Delegate>> item)
|
||||||
|
{
|
||||||
|
return Delegates.Remove(item.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Delegates.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsReadOnly
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable implementation
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<string, List<Delegate>>> GetEnumerator()
|
||||||
|
{
|
||||||
|
return Delegates.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable implementation
|
||||||
|
|
||||||
|
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return Delegates.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ namespace Bind.Structures
|
||||||
|
|
||||||
class Enum
|
class Enum
|
||||||
{
|
{
|
||||||
static StringBuilder translator = new StringBuilder();
|
|
||||||
string _name, _type;
|
string _name, _type;
|
||||||
|
|
||||||
// Returns true if the enum contains a collection of flags, i.e. 1, 2, 4, 8, ...
|
// Returns true if the enum contains a collection of flags, i.e. 1, 2, 4, 8, ...
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace Bind.Structures
|
||||||
Pointer = t.Pointer;
|
Pointer = t.Pointer;
|
||||||
Reference = t.Reference;
|
Reference = t.Reference;
|
||||||
ElementCount = t.ElementCount;
|
ElementCount = t.ElementCount;
|
||||||
|
IsEnum = t.IsEnum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +57,8 @@ namespace Bind.Structures
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Public Members
|
||||||
|
|
||||||
public string QualifiedType
|
public string QualifiedType
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -176,15 +179,8 @@ namespace Bind.Structures
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
//// Returns true if parameter is an enum.
|
// Set to true if parameter is an enum.
|
||||||
//public bool IsEnum
|
public bool IsEnum { get; set; }
|
||||||
//{
|
|
||||||
// get
|
|
||||||
// {
|
|
||||||
// return Enum.GLEnums.ContainsKey(CurrentType) ||
|
|
||||||
// Enum.AuxEnums.ContainsKey(CurrentType);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
#region IndirectionLevel
|
#region IndirectionLevel
|
||||||
|
|
||||||
|
@ -309,6 +305,8 @@ namespace Bind.Structures
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region IComparable<Type> Members
|
#region IComparable<Type> Members
|
||||||
|
|
||||||
public int CompareTo(Type other)
|
public int CompareTo(Type other)
|
||||||
|
|
|
@ -238,19 +238,16 @@ namespace Bind
|
||||||
// Merges the specified delegate collections.
|
// Merges the specified delegate collections.
|
||||||
internal static void Merge(DelegateCollection delegates, DelegateCollection new_delegates)
|
internal static void Merge(DelegateCollection delegates, DelegateCollection new_delegates)
|
||||||
{
|
{
|
||||||
foreach (var d in new_delegates)
|
foreach (var d in new_delegates.Values.SelectMany(v => v))
|
||||||
{
|
{
|
||||||
Merge(delegates, d.Value);
|
Merge(delegates, d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merges the given delegate into the delegate list.
|
// Merges the given delegate into the delegate list.
|
||||||
internal static void Merge(DelegateCollection delegates, Delegate t)
|
internal static void Merge(DelegateCollection delegates, Delegate t)
|
||||||
{
|
{
|
||||||
if (!delegates.ContainsKey(t.Name))
|
delegates.Add(t);
|
||||||
delegates.Add(t.Name, t);
|
|
||||||
else
|
|
||||||
Console.WriteLine("Function '{0}' redefined", t.Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -255,23 +255,18 @@ namespace Bind
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Check whether we are adding to an existing delegate or creating a new one.
|
// Check whether we are adding to an existing delegate or creating a new one.
|
||||||
Delegate d = null;
|
var d = new Delegate
|
||||||
if (delegates.ContainsKey(name))
|
|
||||||
{
|
{
|
||||||
d = delegates[name];
|
Name = name,
|
||||||
}
|
EntryPoint = name,
|
||||||
else
|
Version = node.GetAttribute("version", String.Empty).Trim(),
|
||||||
{
|
Category = node.GetAttribute("category", String.Empty).Trim(),
|
||||||
d = new Delegate();
|
DeprecatedVersion = node.GetAttribute("deprecated", String.Empty).Trim(),
|
||||||
d.Name = name;
|
Deprecated = !String.IsNullOrEmpty(node.GetAttribute("deprecated", String.Empty)),
|
||||||
d.Version = node.GetAttribute("version", String.Empty).Trim();
|
Extension = node.GetAttribute("extension", String.Empty).Trim() ?? "Core",
|
||||||
d.Category = node.GetAttribute("category", String.Empty).Trim();
|
};
|
||||||
d.DeprecatedVersion = node.GetAttribute("deprecated", String.Empty).Trim();
|
|
||||||
d.Deprecated = !String.IsNullOrEmpty(d.DeprecatedVersion);
|
|
||||||
d.Extension = node.GetAttribute("extension", String.Empty).Trim() ?? "Core";
|
|
||||||
if (!extensions.Contains(d.Extension))
|
if (!extensions.Contains(d.Extension))
|
||||||
extensions.Add(d.Extension);
|
extensions.Add(d.Extension);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
|
foreach (XPathNavigator param in node.SelectChildren(XPathNodeType.Element))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue