[generator] Use ordinal string comparison. (#1022)
Test results when running the generator for XM/full: Profile output size before: 9,4 GB Profile output size after: 5,6 GB Duration before: 21,5 s Duration after: 19,0 s Difference: - 2,5 s = -11,6 % Total memory usage barely changed (5kb less within a total of 1,0 GB), but the number of method calls fell drastically: Method calls before: 868.053.383 Method calls after: 492.325.187 Difference: - 375.728.196 = -43,3% The top 10 method calls also changed significantly. Method call summary before ``` Total(ms) Self(ms) Calls Method name 128879 28400 3509251 Mono.Globalization.Unicode.SimpleCollator:CompareInternal (string,int,int,string,int,int,bool&,bool&,bool,bool,Mono.Globalization.Unicode.SimpleCollator/Context&) 16074 16074 79118946 Mono.Globalization.Unicode.CodePointIndexer:ToIndex (int) 15952 10492 26747901 Mono.Globalization.Unicode.MSCompatUnicodeTable:Category (int) 26425 10473 26747901 Mono.Globalization.Unicode.SimpleCollator:Category (int) 14743 8679 14952304 Mono.Globalization.Unicode.MSCompatUnicodeTable:IsIgnorable (int,byte) 31345 8113 10413595 System.RuntimeType:GetBaseType () 12266 7303 12523021 Mono.Globalization.Unicode.SimpleCollator:GetContraction (string,int,int) 20555 5812 14952304 Mono.Globalization.Unicode.SimpleCollator:IsIgnorable (int,System.Globalization.CompareOptions) 93341 5529 2674913 System.MonoCustomAttrs:GetCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type,bool) 8229 5337 13551378 System.RuntimeType:GetAttributeFlagsImpl () ``` Method call summary after ``` Total(ms) Self(ms) Calls Method name 31646 8168 10412459 System.RuntimeType:GetBaseType () 94899 5672 2674880 System.MonoCustomAttrs:GetCustomAttributes (System.Reflection.ICustomAttributeProvider,System.Type,bool) 8343 5395 13550176 System.RuntimeType:GetAttributeFlagsImpl () 5646 5243 2914268 (wrapper managed-to-native) System.MonoCustomAttrs:GetCustomAttributesInternal (System.Reflection.ICustomAttributeProvider,System.Type,bool) 5147 5147 9727785 (wrapper managed-to-native) object:__icall_wrapper_ves_icall_array_new_specific (intptr,int) 11140 4432 10948127 System.Type:get_Attributes () 19601 4362 10716826 System.Type:get_IsInterface () 15238 4344 10716826 System.RuntimeTypeHandle:IsInterface (System.RuntimeType) 4133 4133 1 (wrapper managed-to-native) System.Threading.WaitHandle:WaitOne_internal (intptr,int) 5922 3851 9541170 (wrapper stelemref) object:virt_stelemref_class (intptr,object) ```
This commit is contained in:
Родитель
d0209f4b27
Коммит
3cf1b75749
|
@ -2177,7 +2177,7 @@ public partial class Generator : IMemberGatherer {
|
|||
if (HasAttribute (pi, typeof (NullAllowedAttribute)))
|
||||
return false;
|
||||
|
||||
if (mi.IsSpecialName && mi.Name.StartsWith ("set_")){
|
||||
if (mi.IsSpecialName && mi.Name.StartsWith ("set_", StringComparison.Ordinal)){
|
||||
if (HasAttribute (mi, typeof (NullAllowedAttribute))){
|
||||
return false;
|
||||
}
|
||||
|
@ -2337,7 +2337,7 @@ public partial class Generator : IMemberGatherer {
|
|||
var marshalDirective = GetAttribute<MarshalDirectiveAttribute> (mi);
|
||||
if (marshalDirective != null && marshalDirective.Library != null) {
|
||||
print (m, "\t\t[DllImport (\"{0}\", EntryPoint=\"{1}\")]", marshalDirective.Library, method_name);
|
||||
} else if (method_name.StartsWith ("xamarin_")) {
|
||||
} else if (method_name.StartsWith ("xamarin_", StringComparison.Ordinal)) {
|
||||
print (m, "\t\t[DllImport (\"__Internal\", EntryPoint=\"{0}\")]", method_name);
|
||||
} else {
|
||||
print (m, "\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"{0}\")]", entry_point);
|
||||
|
@ -3055,7 +3055,7 @@ public partial class Generator : IMemberGatherer {
|
|||
print ("namespace {0} {{", ns.CoreObjCRuntime); indent++;
|
||||
print ("[CompilerGenerated]");
|
||||
print ("static partial class Libraries {"); indent++;
|
||||
foreach (var library_info in libraries.OrderBy (v => v.Key)) {
|
||||
foreach (var library_info in libraries.OrderBy (v => v.Key, StringComparer.Ordinal)) {
|
||||
var library_name = library_info.Key;
|
||||
var library_path = library_info.Value;
|
||||
print ("static public class {0} {{", library_name.Replace (".", string.Empty)); indent++;
|
||||
|
@ -3201,7 +3201,7 @@ public partial class Generator : IMemberGatherer {
|
|||
} else if (pi.PropertyType == typeof (string)){
|
||||
getter = "GetStringValue ({0})";
|
||||
setter = "SetStringValue ({0}, value)";
|
||||
} else if (pi.PropertyType.Name.StartsWith ("NSDictionary")){
|
||||
} else if (pi.PropertyType.Name.StartsWith ("NSDictionary", StringComparison.Ordinal)){
|
||||
if (pi.PropertyType.IsGenericType) {
|
||||
var genericParameters = pi.PropertyType.GetGenericArguments ();
|
||||
// we want to keep {0} for later yet add the params for the template.
|
||||
|
@ -3428,7 +3428,7 @@ public partial class Generator : IMemberGatherer {
|
|||
{
|
||||
string prefix = new string ('\t', level);
|
||||
Console.WriteLine ("{2} {0} - {1}", gt.Type.Name, gt.ImplementsAppearance ? "APPEARANCE" : "", prefix);
|
||||
foreach (var c in (from s in gt.Children orderby s.Type.FullName select s))
|
||||
foreach (var c in (from s in gt.Children .OrderBy ( s => s.Type.FullName, StringComparer.Ordinal) select s))
|
||||
DumpChildren (level+1, c);
|
||||
}
|
||||
|
||||
|
@ -3741,9 +3741,9 @@ public partial class Generator : IMemberGatherer {
|
|||
}
|
||||
// Unified internal methods automatically get a _ appended
|
||||
if (minfo.is_extension_method && minfo.method.IsSpecialName) {
|
||||
if (name.StartsWith ("get_"))
|
||||
if (name.StartsWith ("get_", StringComparison.Ordinal))
|
||||
name = "Get" + name.Substring (4);
|
||||
else if (name.StartsWith ("set_"))
|
||||
else if (name.StartsWith ("set_", StringComparison.Ordinal))
|
||||
name = "Set" + name.Substring (4);
|
||||
}
|
||||
sb.Append (name);
|
||||
|
@ -3821,7 +3821,7 @@ public partial class Generator : IMemberGatherer {
|
|||
print (w, "//\n// Auto-generated from generator.cs, do not edit\n//");
|
||||
print (w, "// We keep references to objects, so warning 414 is expected\n");
|
||||
print (w, "#pragma warning disable 414\n");
|
||||
print (w, ns.ImplicitNamespaces.OrderByDescending (n => n.StartsWith ("System")).ThenBy (n => n.Length).Select (n => "using " + n + ";"));
|
||||
print (w, ns.ImplicitNamespaces.OrderByDescending (n => n.StartsWith ("System", StringComparison.Ordinal)).ThenBy (n => n.Length).Select (n => "using " + n + ";"));
|
||||
print (w, "");
|
||||
}
|
||||
|
||||
|
@ -4972,7 +4972,7 @@ public partial class Generator : IMemberGatherer {
|
|||
// If we're doing a setter for a weak property that is protocolized event back
|
||||
// we need to put in a check to verify you aren't stomping the "internal underscore"
|
||||
// generated delegate. We check CheckForEventAndDelegateMismatches global to disable the checks
|
||||
if (pi.Name.StartsWith ("Weak")) {
|
||||
if (pi.Name.StartsWith ("Weak", StringComparison.Ordinal)) {
|
||||
string delName = pi.Name.Substring(4);
|
||||
if (SafeIsProtocolizedEventBacked (delName, type))
|
||||
print ("\t{0}.EnsureDelegateAssignIsNotOverwritingInternalDelegate ({1}, value, {2});", ApplicationClassName, string.IsNullOrEmpty (var_name) ? "null" : var_name, GetDelegateTypePropertyName (delName));
|
||||
|
@ -5386,18 +5386,18 @@ public partial class Generator : IMemberGatherer {
|
|||
group fullname by ns into g
|
||||
select new {Namespace = g.Key, Fullname=g};
|
||||
|
||||
foreach (var group in groupedTypes.OrderBy (v => v.Namespace)) {
|
||||
foreach (var group in groupedTypes.OrderBy (v => v.Namespace, StringComparer.Ordinal)) {
|
||||
if (group.Namespace != null) {
|
||||
print ("namespace {0} {{", group.Namespace);
|
||||
indent++;
|
||||
}
|
||||
|
||||
foreach (var deltype in group.Fullname.OrderBy (v => v)) {
|
||||
int p = deltype.LastIndexOf (".");
|
||||
foreach (var deltype in group.Fullname.OrderBy (v => v, StringComparer.Ordinal)) {
|
||||
int p = deltype.LastIndexOf (".", StringComparison.Ordinal);
|
||||
var shortName = deltype.Substring (p+1);
|
||||
var mi = delegateTypes [deltype];
|
||||
|
||||
if (shortName.StartsWith ("Func<"))
|
||||
if (shortName.StartsWith ("Func<", StringComparison.Ordinal))
|
||||
continue;
|
||||
|
||||
var del = mi.DeclaringType;
|
||||
|
@ -5518,7 +5518,7 @@ public partial class Generator : IMemberGatherer {
|
|||
{
|
||||
var allProtocolMethods = new List<MethodInfo> ();
|
||||
var allProtocolProperties = new List<PropertyInfo> ();
|
||||
var ifaces = (IEnumerable<Type>) type.GetInterfaces ().Concat (new Type [] { ReflectionExtensions.GetBaseType (type) }).OrderBy (v => v.FullName);
|
||||
var ifaces = (IEnumerable<Type>) type.GetInterfaces ().Concat (new Type [] { ReflectionExtensions.GetBaseType (type) }).OrderBy (v => v.FullName, StringComparer.Ordinal);
|
||||
|
||||
if (type.Namespace != null) {
|
||||
print ("namespace {0} {{", type.Namespace);
|
||||
|
@ -5967,7 +5967,7 @@ public partial class Generator : IMemberGatherer {
|
|||
implements_list.Add (iface);
|
||||
}
|
||||
|
||||
implements_list.Sort ();
|
||||
implements_list.Sort (StringComparer.Ordinal);
|
||||
|
||||
if (is_protocol)
|
||||
implements_list.Insert (0, "I" + type.Name);
|
||||
|
@ -6025,7 +6025,7 @@ public partial class Generator : IMemberGatherer {
|
|||
indent++;
|
||||
|
||||
if (!is_model && !is_partial) {
|
||||
foreach (var ea in selectors [type].OrderBy (s => s)) {
|
||||
foreach (var ea in selectors [type].OrderBy (s => s, StringComparer.Ordinal)) {
|
||||
var selectorField = SelectorField (ea, true);
|
||||
if (!InlineSelectors) {
|
||||
selectorField = selectorField.Substring (0, selectorField.Length - 6 /* Handle */);
|
||||
|
@ -6174,12 +6174,12 @@ public partial class Generator : IMemberGatherer {
|
|||
|
||||
var bound_methods = new List<string> (); // List of methods bound on the class itself (not via protocols)
|
||||
var generated_methods = new List<MemberInformation> (); // All method that have been generated
|
||||
foreach (var mi in GetTypeContractMethods (type).OrderByDescending (m => m.Name == "Constructor").ThenBy (m => m.Name)) {
|
||||
foreach (var mi in GetTypeContractMethods (type).OrderByDescending (m => m.Name == "Constructor").ThenBy (m => m.Name, StringComparer.Ordinal)) {
|
||||
if (mi.IsSpecialName || (mi.Name == "Constructor" && type != mi.DeclaringType))
|
||||
continue;
|
||||
|
||||
#if RETAIN_AUDITING
|
||||
if (mi.Name.StartsWith ("Set"))
|
||||
if (mi.Name.StartsWith ("Set", StringComparison.Ordinal))
|
||||
foreach (ParameterInfo pi in mi.GetParameters ())
|
||||
if (IsWrappedType (pi.ParameterType) || pi.ParameterType.IsArray) {
|
||||
Console.WriteLine ("AUDIT: {0}", mi);
|
||||
|
@ -6248,7 +6248,7 @@ public partial class Generator : IMemberGatherer {
|
|||
var bound_properties = new List<string> (); // List of properties bound on the class itself (not via protocols)
|
||||
var generated_properties = new List<string> (); // All properties that have been generated
|
||||
|
||||
foreach (var pi in GetTypeContractProperties (type).OrderBy (p => p.Name)) {
|
||||
foreach (var pi in GetTypeContractProperties (type).OrderBy (p => p.Name, StringComparer.Ordinal)) {
|
||||
|
||||
#if !XAMCORE_2_0
|
||||
if (HasAttribute (pi, typeof (AlphaAttribute)) && Alpha == false)
|
||||
|
@ -6304,7 +6304,7 @@ public partial class Generator : IMemberGatherer {
|
|||
}
|
||||
|
||||
if (field_exports.Count != 0){
|
||||
foreach (var field_pi in field_exports.OrderBy (f => f.Name)) {
|
||||
foreach (var field_pi in field_exports.OrderBy (f => f.Name, StringComparer.Ordinal)) {
|
||||
var fieldAttr = (FieldAttribute) field_pi.GetCustomAttributes (typeof (FieldAttribute), true) [0];
|
||||
string library_name;
|
||||
string library_path = null;
|
||||
|
@ -6336,7 +6336,7 @@ public partial class Generator : IMemberGatherer {
|
|||
} else {
|
||||
library_name = type.Namespace;
|
||||
// note: not every binding namespace will start with ns.Prefix (e.g. MonoTouch.)
|
||||
if (!String.IsNullOrEmpty (ns.Prefix) && library_name.StartsWith (ns.Prefix)) {
|
||||
if (!String.IsNullOrEmpty (ns.Prefix) && library_name.StartsWith (ns.Prefix, StringComparison.Ordinal)) {
|
||||
library_name = library_name.Substring (ns.Prefix.Length + 1);
|
||||
library_name = library_name.Replace (".", string.Empty); // Remove dots from namespaces
|
||||
}
|
||||
|
@ -6481,7 +6481,7 @@ public partial class Generator : IMemberGatherer {
|
|||
int delidx = 0;
|
||||
foreach (var dtype in bta.Events) {
|
||||
string delName = bta.Delegates [delidx++];
|
||||
delName = delName.StartsWith ("Weak") ? delName.Substring(4) : delName;
|
||||
delName = delName.StartsWith ("Weak", StringComparison.Ordinal) ? delName.Substring(4) : delName;
|
||||
|
||||
// Here's the problem:
|
||||
// If you have two or more types in an inheritence structure in the binding that expose events
|
||||
|
@ -6596,7 +6596,7 @@ public partial class Generator : IMemberGatherer {
|
|||
|
||||
string previous_miname = null;
|
||||
int miname_count = 0;
|
||||
foreach (var mi in dtype.GatherMethods ().OrderBy (m => m.Name)) {
|
||||
foreach (var mi in dtype.GatherMethods ().OrderBy (m => m.Name, StringComparer.Ordinal)) {
|
||||
if (ShouldSkipEventGeneration (mi))
|
||||
continue;
|
||||
|
||||
|
@ -6742,7 +6742,7 @@ public partial class Generator : IMemberGatherer {
|
|||
print ("return false;");
|
||||
--indent;
|
||||
print ("IntPtr selHandle = sel == null ? IntPtr.Zero : sel.Handle;");
|
||||
foreach (var mi in noDefaultValue.OrderBy (m => m.Name)) {
|
||||
foreach (var mi in noDefaultValue.OrderBy (m => m.Name, StringComparer.Ordinal)) {
|
||||
if (InlineSelectors) {
|
||||
var eattrs = mi.GetCustomAttributes (typeof (ExportAttribute), false);
|
||||
var export = (ExportAttribute)eattrs[0];
|
||||
|
@ -6778,8 +6778,8 @@ public partial class Generator : IMemberGatherer {
|
|||
int minameCount = 0;
|
||||
repeatedDelegateApiNames.Clear ();
|
||||
// Now add the instance vars and event handlers
|
||||
foreach (var dtype in bta.Events.OrderBy (d => d.Name)) {
|
||||
foreach (var mi in dtype.GatherMethods ().OrderBy (m => m.Name)) {
|
||||
foreach (var dtype in bta.Events.OrderBy (d => d.Name, StringComparer.Ordinal)) {
|
||||
foreach (var mi in dtype.GatherMethods ().OrderBy (m => m.Name, StringComparer.Ordinal)) {
|
||||
if (ShouldSkipEventGeneration (mi))
|
||||
continue;
|
||||
|
||||
|
@ -6834,7 +6834,7 @@ public partial class Generator : IMemberGatherer {
|
|||
if (instance_fields_to_clear_on_dispose.Count > 0) {
|
||||
print ("if (Handle == IntPtr.Zero) {");
|
||||
indent++;
|
||||
foreach (var field in instance_fields_to_clear_on_dispose.OrderBy (f => f))
|
||||
foreach (var field in instance_fields_to_clear_on_dispose.OrderBy (f => f, StringComparer.Ordinal))
|
||||
print ("{0} = null;", field);
|
||||
indent--;
|
||||
print ("}");
|
||||
|
@ -6867,7 +6867,7 @@ public partial class Generator : IMemberGatherer {
|
|||
if (appearance_selectors != null){
|
||||
var currently_ignored_fields = new List<string> ();
|
||||
|
||||
foreach (MemberInfo mi in appearance_selectors.OrderBy (m => m.Name)) {
|
||||
foreach (MemberInfo mi in appearance_selectors.OrderBy (m => m.Name, StringComparer.Ordinal)) {
|
||||
if (mi is MethodInfo)
|
||||
GenerateMethod (type, mi as MethodInfo,
|
||||
is_model: false,
|
||||
|
@ -6933,7 +6933,7 @@ public partial class Generator : IMemberGatherer {
|
|||
print ("//");
|
||||
|
||||
print ("public static partial class Notifications {\n");
|
||||
foreach (var property in notifications.OrderBy (p => p.Name)) {
|
||||
foreach (var property in notifications.OrderBy (p => p.Name, StringComparer.Ordinal)) {
|
||||
string notification_name = GetNotificationName (property);
|
||||
string notification_center = GetNotificationCenter (property);
|
||||
|
||||
|
@ -6959,7 +6959,7 @@ public partial class Generator : IMemberGatherer {
|
|||
// Copy delegates from the API files into the output if they were declared there
|
||||
//
|
||||
var rootAssembly = types [0].Assembly;
|
||||
foreach (var deltype in trampolines.Keys.OrderBy (d => d.Name)) {
|
||||
foreach (var deltype in trampolines.Keys.OrderBy (d => d.Name, StringComparer.Ordinal)) {
|
||||
if (deltype.Assembly != rootAssembly)
|
||||
continue;
|
||||
|
||||
|
@ -6974,7 +6974,7 @@ public partial class Generator : IMemberGatherer {
|
|||
print ("//");
|
||||
}
|
||||
// Now add the EventArgs classes
|
||||
foreach (var eaclass in eventArgTypes.Keys.OrderBy (e => e)) {
|
||||
foreach (var eaclass in eventArgTypes.Keys.OrderBy (e => e, StringComparer.Ordinal)) {
|
||||
if (skipGeneration.ContainsKey (eaclass)){
|
||||
continue;
|
||||
}
|
||||
|
@ -6986,14 +6986,14 @@ public partial class Generator : IMemberGatherer {
|
|||
print ("public {0} ({1})", eaclass, RenderParameterDecl (pars.Skip (1), true));
|
||||
print ("{");
|
||||
indent++;
|
||||
foreach (var p in pars.Skip (minPars).OrderBy (p => p.Name)) {
|
||||
foreach (var p in pars.Skip (minPars).OrderBy (p => p.Name, StringComparer.Ordinal)) {
|
||||
print ("this.{0} = {1};", GetPublicParameterName (p), p.Name);
|
||||
}
|
||||
indent--;
|
||||
print ("}");
|
||||
|
||||
// Now print the properties
|
||||
foreach (var p in pars.Skip (minPars).OrderBy (p => p.Name)) {
|
||||
foreach (var p in pars.Skip (minPars).OrderBy (p => p.Name, StringComparer.Ordinal)) {
|
||||
var bareType = p.ParameterType.IsByRef ? p.ParameterType.GetElementType () : p.ParameterType;
|
||||
|
||||
print ("public {0} {1} {{ get; set; }}", RenderType (bareType), GetPublicParameterName (p));
|
||||
|
@ -7008,7 +7008,7 @@ public partial class Generator : IMemberGatherer {
|
|||
print ("//");
|
||||
}
|
||||
|
||||
foreach (var async_type in async_result_types.OrderBy (t => t.Item1)) {
|
||||
foreach (var async_type in async_result_types.OrderBy (t => t.Item1, StringComparer.Ordinal)) {
|
||||
if (async_result_types_emitted.Contains (async_type.Item1))
|
||||
continue;
|
||||
async_result_types_emitted.Add (async_type.Item1);
|
||||
|
@ -7146,7 +7146,7 @@ public partial class Generator : IMemberGatherer {
|
|||
bool ShouldSkipEventGeneration (MethodInfo mi)
|
||||
{
|
||||
// Skip property getter/setters
|
||||
if (mi.IsSpecialName && (mi.Name.StartsWith ("get_") || mi.Name.StartsWith ("set_")))
|
||||
if (mi.IsSpecialName && (mi.Name.StartsWith ("get_", StringComparison.Ordinal) || mi.Name.StartsWith ("set_", StringComparison.Ordinal)))
|
||||
return true;
|
||||
|
||||
if (mi.IsUnavailable ())
|
||||
|
@ -7167,8 +7167,8 @@ public partial class Generator : IMemberGatherer {
|
|||
// Safely strips away any Weak from the beginning of either delegate and returns if they match
|
||||
static bool CompareTwoDelegateNames (string lhsDel, string rhsDel)
|
||||
{
|
||||
lhsDel = lhsDel.StartsWith ("Weak") ? lhsDel.Substring (4): lhsDel;
|
||||
rhsDel = rhsDel.StartsWith ("Weak") ? rhsDel.Substring (4): rhsDel;
|
||||
lhsDel = lhsDel.StartsWith ("Weak", StringComparison.Ordinal) ? lhsDel.Substring (4): lhsDel;
|
||||
rhsDel = rhsDel.StartsWith ("Weak", StringComparison.Ordinal) ? rhsDel.Substring (4): rhsDel;
|
||||
return lhsDel == rhsDel;
|
||||
}
|
||||
|
||||
|
@ -7216,7 +7216,7 @@ public partial class Generator : IMemberGatherer {
|
|||
|
||||
static string Capitalize (string str)
|
||||
{
|
||||
if (str.StartsWith ("@"))
|
||||
if (str.StartsWith ("@", StringComparison.Ordinal))
|
||||
return char.ToUpper (str[1]) + str.Substring (2);
|
||||
|
||||
return char.ToUpper (str[0]) + str.Substring (1);
|
||||
|
@ -7235,7 +7235,7 @@ public partial class Generator : IMemberGatherer {
|
|||
{
|
||||
// TODO: fetch the NotificationAttribute, see if there is an override there.
|
||||
var name = pi.Name;
|
||||
if (name.EndsWith ("Notification"))
|
||||
if (name.EndsWith ("Notification", StringComparison.Ordinal))
|
||||
return name.Substring (0, name.Length-"Notification".Length);
|
||||
return name;
|
||||
}
|
||||
|
@ -7346,7 +7346,7 @@ public partial class Generator : IMemberGatherer {
|
|||
throw new BindingException (1004, true, "The delegate method {0}.{1} is missing the [EventArgs] attribute (has {2} parameters)", mi.DeclaringType.FullName, mi.Name, mi.GetParameters ().Length);
|
||||
|
||||
var ea = (EventArgsAttribute) a;
|
||||
if (ea.ArgName.EndsWith ("EventArgs"))
|
||||
if (ea.ArgName.EndsWith ("EventArgs", StringComparison.Ordinal))
|
||||
throw new BindingException (1005, true, "EventArgs in {0}.{1} attribute should not include the text `EventArgs' at the end", mi.DeclaringType.FullName, mi.Name);
|
||||
|
||||
if (ea.SkipGeneration){
|
||||
|
|
Загрузка…
Ссылка в новой задаче