mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
564 lines
20 KiB
564 lines
20 KiB
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) |
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) |
|
|
|
using System; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
using System.Text; |
|
|
|
using ICSharpCode.SharpDevelop.Dom.ReflectionLayer; |
|
using Mono.Cecil; |
|
using Mono.Collections.Generic; |
|
|
|
namespace ICSharpCode.SharpDevelop.Dom |
|
{ |
|
public static class CecilReader |
|
{ |
|
sealed class DummyAssemblyResolver : IAssemblyResolver |
|
{ |
|
public AssemblyDefinition Resolve(AssemblyNameReference name) |
|
{ |
|
return null; |
|
} |
|
|
|
public AssemblyDefinition Resolve(string fullName) |
|
{ |
|
return null; |
|
} |
|
|
|
public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) |
|
{ |
|
throw new NotImplementedException(); |
|
} |
|
|
|
public AssemblyDefinition Resolve(string fullName, ReaderParameters parameters) |
|
{ |
|
throw new NotImplementedException(); |
|
} |
|
} |
|
|
|
public static ReflectionProjectContent LoadAssembly(string fileName, ProjectContentRegistry registry) |
|
{ |
|
if (fileName == null) |
|
throw new ArgumentNullException("fileName"); |
|
if (registry == null) |
|
throw new ArgumentNullException("registry"); |
|
LoggingService.Info("Cecil: Load from " + fileName); |
|
AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(fileName, new ReaderParameters { AssemblyResolver = new DummyAssemblyResolver() }); |
|
List<DomAssemblyName> referencedAssemblies = new List<DomAssemblyName>(); |
|
foreach (ModuleDefinition module in asm.Modules) { |
|
foreach (AssemblyNameReference anr in module.AssemblyReferences) { |
|
referencedAssemblies.Add(new DomAssemblyName(anr.FullName)); |
|
} |
|
} |
|
return new CecilProjectContent(asm.Name.FullName, fileName, referencedAssemblies.ToArray(), asm, registry); |
|
} |
|
|
|
static void AddAttributes(IProjectContent pc, IEntity member, IList<IAttribute> list, ICustomAttributeProvider attributeProvider) |
|
{ |
|
if (!attributeProvider.HasCustomAttributes) |
|
return; |
|
foreach (CustomAttribute att in attributeProvider.CustomAttributes) { |
|
DefaultAttribute a = new DefaultAttribute(CreateType(pc, member, att.Constructor.DeclaringType)); |
|
// Currently Cecil returns string instead of TypeReference for typeof() arguments to attributes |
|
try { |
|
foreach (var argument in att.ConstructorArguments) { |
|
a.PositionalArguments.Add(GetValue(pc, member, argument)); |
|
} |
|
foreach (CustomAttributeNamedArgument entry in att.Properties) { |
|
// some obfuscated assemblies may contain duplicate named arguments; we'll have to ignore those |
|
if (!a.NamedArguments.ContainsKey(entry.Name)) |
|
a.NamedArguments.Add(entry.Name, GetValue(pc, member, entry.Argument)); |
|
} |
|
} catch (InvalidOperationException) { |
|
// Workaround for Cecil bug. (some types cannot be resolved) |
|
} |
|
list.Add(a); |
|
} |
|
} |
|
|
|
static object GetValue(IProjectContent pc, IEntity member, CustomAttributeArgument argument) |
|
{ |
|
if (argument.Value is TypeReference) |
|
return CreateType(pc, member, (TypeReference)argument.Value); |
|
else |
|
return argument.Value; |
|
} |
|
|
|
static void AddConstraintsFromType(ITypeParameter tp, GenericParameter g) |
|
{ |
|
foreach (TypeReference constraint in g.Constraints) { |
|
if (tp.Method != null) { |
|
tp.Constraints.Add(CreateType(tp.Class.ProjectContent, tp.Method, constraint)); |
|
} else { |
|
tp.Constraints.Add(CreateType(tp.Class.ProjectContent, tp.Class, constraint)); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Create a SharpDevelop return type from a Cecil type reference. |
|
/// </summary> |
|
internal static IReturnType CreateType(IProjectContent pc, IEntity member, TypeReference type, ICustomAttributeProvider attributeProvider = null) |
|
{ |
|
int typeIndex = 0; |
|
return CreateType(pc, member, type, attributeProvider, ref typeIndex); |
|
} |
|
|
|
static IReturnType CreateType(IProjectContent pc, IEntity member, TypeReference type, ICustomAttributeProvider attributeProvider, ref int typeIndex) |
|
{ |
|
while (type is OptionalModifierType || type is RequiredModifierType) { |
|
type = ((TypeSpecification)type).ElementType; |
|
} |
|
if (type == null) { |
|
LoggingService.Warn("CecilReader: Null type for: " + member); |
|
return new VoidReturnType(pc); |
|
} |
|
if (type is ByReferenceType) { |
|
// TODO: Use ByRefRefReturnType |
|
return CreateType(pc, member, (type as ByReferenceType).ElementType, attributeProvider, ref typeIndex); |
|
} else if (type is PointerType) { |
|
typeIndex++; |
|
return new PointerReturnType(CreateType(pc, member, (type as PointerType).ElementType, attributeProvider, ref typeIndex)); |
|
} else if (type is ArrayType) { |
|
typeIndex++; |
|
return new ArrayReturnType(pc, CreateType(pc, member, (type as ArrayType).ElementType, attributeProvider, ref typeIndex), (type as ArrayType).Rank); |
|
} else if (type is GenericInstanceType) { |
|
GenericInstanceType gType = (GenericInstanceType)type; |
|
IReturnType baseType = CreateType(pc, member, gType.ElementType, attributeProvider, ref typeIndex); |
|
IReturnType[] para = new IReturnType[gType.GenericArguments.Count]; |
|
for (int i = 0; i < para.Length; ++i) { |
|
typeIndex++; |
|
para[i] = CreateType(pc, member, gType.GenericArguments[i], attributeProvider, ref typeIndex); |
|
} |
|
return new ConstructedReturnType(baseType, para); |
|
} else if (type is GenericParameter) { |
|
GenericParameter typeGP = type as GenericParameter; |
|
if (typeGP.Owner is MethodDefinition) { |
|
IMethod method = member as IMethod; |
|
if (method != null) { |
|
if (typeGP.Position < method.TypeParameters.Count) { |
|
return new GenericReturnType(method.TypeParameters[typeGP.Position]); |
|
} |
|
} |
|
return new GenericReturnType(new DefaultTypeParameter(method, typeGP.Name, typeGP.Position)); |
|
} else { |
|
IClass c = (member is IClass) ? (IClass)member : (member is IMember) ? ((IMember)member).DeclaringType : null; |
|
if (c != null && typeGP.Position < c.TypeParameters.Count) { |
|
if (c.TypeParameters[typeGP.Position].Name == type.Name) { |
|
return new GenericReturnType(c.TypeParameters[typeGP.Position]); |
|
} |
|
} |
|
return new GenericReturnType(new DefaultTypeParameter(c, typeGP.Name, typeGP.Position)); |
|
} |
|
} else { |
|
string name = type.FullName; |
|
if (name == null) |
|
throw new ApplicationException("type.FullName returned null. Type: " + type.ToString()); |
|
|
|
int typeParameterCount; |
|
if (name.IndexOf('/') > 0) { |
|
typeParameterCount = 0; |
|
StringBuilder newName = new StringBuilder(); |
|
foreach (string namepart in name.Split('/')) { |
|
if (newName.Length > 0) |
|
newName.Append('.'); |
|
int partTypeParameterCount; |
|
newName.Append(ReflectionClass.SplitTypeParameterCountFromReflectionName(namepart, out partTypeParameterCount)); |
|
typeParameterCount += partTypeParameterCount; |
|
} |
|
name = newName.ToString(); |
|
} else { |
|
name = ReflectionClass.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount); |
|
} |
|
|
|
if (typeParameterCount == 0 && name == "System.Object" && HasDynamicAttribute(attributeProvider, typeIndex)) |
|
return new DynamicReturnType(pc); |
|
|
|
IClass c = pc.GetClass(name, typeParameterCount); |
|
if (c != null) { |
|
return c.DefaultReturnType; |
|
} else { |
|
// example where name is not found: pointers like System.Char* |
|
// or when the class is in a assembly that is not referenced |
|
return new GetClassReturnType(pc, name, typeParameterCount); |
|
} |
|
} |
|
} |
|
|
|
static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex) |
|
{ |
|
if (attributeProvider == null || attributeProvider.HasCustomAttributes == false) |
|
return false; |
|
foreach (CustomAttribute a in attributeProvider.CustomAttributes) { |
|
if (a.Constructor.DeclaringType.FullName == "System.Runtime.CompilerServices.DynamicAttribute") { |
|
if (a.ConstructorArguments.Count == 1) { |
|
CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[]; |
|
if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool) |
|
return (bool)values[typeIndex].Value; |
|
} |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
private sealed class CecilProjectContent : ReflectionProjectContent |
|
{ |
|
public CecilProjectContent(string fullName, string fileName, DomAssemblyName[] referencedAssemblies, |
|
AssemblyDefinition assembly, ProjectContentRegistry registry) |
|
: base(fullName, fileName, referencedAssemblies, registry) |
|
{ |
|
foreach (ModuleDefinition module in assembly.Modules) { |
|
AddTypes(module.Types); |
|
} |
|
AddAttributes(this, null, this.AssemblyCompilationUnit.Attributes, assembly); |
|
InitializeSpecialClasses(); |
|
this.AssemblyCompilationUnit.Freeze(); |
|
} |
|
|
|
void AddTypes(Collection<TypeDefinition> types) |
|
{ |
|
foreach (TypeDefinition td in types) { |
|
if ((td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { |
|
string name = td.FullName; |
|
if (name.Length == 0 || name[0] == '<') |
|
continue; |
|
name = ReflectionClass.SplitTypeParameterCountFromReflectionName(name); |
|
AddClassToNamespaceListInternal(new CecilClass(this.AssemblyCompilationUnit, null, td, name)); |
|
} |
|
} |
|
} |
|
} |
|
|
|
private sealed class CecilClass : DefaultClass |
|
{ |
|
public static bool IsDelegate(TypeDefinition type) |
|
{ |
|
if (type.BaseType == null) |
|
return false; |
|
else |
|
return type.BaseType.FullName == "System.Delegate" |
|
|| type.BaseType.FullName == "System.MulticastDelegate"; |
|
} |
|
|
|
protected override bool KeepInheritanceTree { |
|
get { return true; } |
|
} |
|
|
|
public CecilClass(ICompilationUnit compilationUnit, IClass declaringType, |
|
TypeDefinition td, string fullName) |
|
: base(compilationUnit, declaringType) |
|
{ |
|
this.FullyQualifiedName = fullName; |
|
|
|
AddAttributes(compilationUnit.ProjectContent, this, this.Attributes, td); |
|
|
|
// set classtype |
|
if (td.IsInterface) { |
|
this.ClassType = ClassType.Interface; |
|
} else if (td.IsEnum) { |
|
this.ClassType = ClassType.Enum; |
|
} else if (td.IsValueType) { |
|
this.ClassType = ClassType.Struct; |
|
} else if (IsDelegate(td)) { |
|
this.ClassType = ClassType.Delegate; |
|
} else { |
|
this.ClassType = ClassType.Class; |
|
} |
|
if (td.GenericParameters.Count > 0) { |
|
foreach (GenericParameter g in td.GenericParameters) { |
|
this.TypeParameters.Add(new DefaultTypeParameter(this, g.Name, g.Position)); |
|
} |
|
int i = 0; |
|
foreach (GenericParameter g in td.GenericParameters) { |
|
AddConstraintsFromType(this.TypeParameters[i++], g); |
|
} |
|
} |
|
|
|
ModifierEnum modifiers = ModifierEnum.None; |
|
|
|
if (td.IsSealed) { |
|
modifiers |= ModifierEnum.Sealed; |
|
} |
|
if (td.IsAbstract) { |
|
modifiers |= ModifierEnum.Abstract; |
|
} |
|
if (td.IsSealed && td.IsAbstract) { |
|
modifiers |= ModifierEnum.Static; |
|
} |
|
|
|
if ((td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic) { |
|
modifiers |= ModifierEnum.Public; |
|
} else if ((td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily) { |
|
modifiers |= ModifierEnum.Protected; |
|
} else if ((td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem) { |
|
modifiers |= ModifierEnum.Protected; |
|
} else { |
|
modifiers |= ModifierEnum.Public; |
|
} |
|
|
|
this.Modifiers = modifiers; |
|
|
|
// set base classes |
|
if (td.BaseType != null) { |
|
BaseTypes.Add(CreateType(this.ProjectContent, this, td.BaseType)); |
|
} |
|
|
|
foreach (TypeReference iface in td.Interfaces) { |
|
BaseTypes.Add(CreateType(this.ProjectContent, this, iface)); |
|
} |
|
|
|
ReflectionClass.ApplySpecialsFromAttributes(this); |
|
|
|
InitMembers(td); |
|
} |
|
|
|
void InitMembers(TypeDefinition type) |
|
{ |
|
string defaultMemberName = null; |
|
foreach (CustomAttribute att in type.CustomAttributes) { |
|
if (att.Constructor.DeclaringType.FullName == "System.Reflection.DefaultMemberAttribute" |
|
&& att.ConstructorArguments.Count == 1) |
|
{ |
|
defaultMemberName = att.ConstructorArguments[0].Value as string; |
|
} |
|
} |
|
|
|
foreach (TypeDefinition nestedType in type.NestedTypes) { |
|
TypeAttributes visibility = nestedType.Attributes & TypeAttributes.VisibilityMask; |
|
if (visibility == TypeAttributes.NestedPublic || visibility == TypeAttributes.NestedFamily |
|
|| visibility == TypeAttributes.NestedFamORAssem) |
|
{ |
|
string name = nestedType.Name; |
|
int pos = name.LastIndexOf('/'); |
|
if (pos > 0) |
|
name = name.Substring(pos + 1); |
|
if (name.Length == 0 || name[0] == '<') |
|
continue; |
|
name = ReflectionClass.SplitTypeParameterCountFromReflectionName(name); |
|
name = this.FullyQualifiedName + "." + name; |
|
InnerClasses.Add(new CecilClass(this.CompilationUnit, this, nestedType, name)); |
|
} |
|
} |
|
|
|
foreach (FieldDefinition field in type.Fields) { |
|
if (IsVisible(field.Attributes) && !field.IsSpecialName) { |
|
DefaultField f = new DefaultField(this, field.Name); |
|
f.Modifiers = TranslateModifiers(field); |
|
f.ReturnType = CreateType(this.ProjectContent, this, field.FieldType, field); |
|
AddAttributes(CompilationUnit.ProjectContent, f, f.Attributes, field); |
|
Fields.Add(f); |
|
} |
|
} |
|
|
|
foreach (PropertyDefinition property in type.Properties) { |
|
AddProperty(defaultMemberName, property); |
|
} |
|
|
|
foreach (EventDefinition eventDef in type.Events) { |
|
if (eventDef.AddMethod != null && IsVisible(eventDef.AddMethod.Attributes)) { |
|
DefaultEvent e = new DefaultEvent(this, eventDef.Name); |
|
if (this.ClassType == ClassType.Interface) { |
|
e.Modifiers = ModifierEnum.Public | ModifierEnum.Abstract; |
|
} else { |
|
e.Modifiers = TranslateModifiers(eventDef); |
|
} |
|
e.ReturnType = CreateType(this.ProjectContent, this, eventDef.EventType, eventDef); |
|
AddAttributes(CompilationUnit.ProjectContent, e, e.Attributes, eventDef); |
|
Events.Add(e); |
|
} |
|
} |
|
|
|
this.AddDefaultConstructorIfRequired = (this.ClassType == ClassType.Struct || this.ClassType == ClassType.Enum); |
|
foreach (MethodDefinition method in type.Methods) { |
|
if (method.IsConstructor || !method.IsSpecialName) { |
|
AddMethod(method); |
|
} |
|
} |
|
} |
|
|
|
void AddProperty(string defaultMemberName, PropertyDefinition property) |
|
{ |
|
if ((property.GetMethod != null && IsVisible(property.GetMethod.Attributes)) |
|
|| (property.SetMethod != null && IsVisible(property.SetMethod.Attributes))) |
|
{ |
|
DefaultProperty p = new DefaultProperty(this, property.Name); |
|
if (this.ClassType == ClassType.Interface) { |
|
p.Modifiers = ModifierEnum.Public | ModifierEnum.Abstract; |
|
} else { |
|
p.Modifiers = TranslateModifiers(property); |
|
} |
|
p.ReturnType = CreateType(this.ProjectContent, this, property.PropertyType, property); |
|
p.CanGet = property.GetMethod != null && IsVisible(property.GetMethod.Attributes); |
|
p.CanSet = property.SetMethod != null && IsVisible(property.SetMethod.Attributes); |
|
if (p.CanGet) |
|
p.GetterModifiers = GetAccessorVisibility(p, property.GetMethod); |
|
if (p.CanSet) |
|
p.SetterModifiers = GetAccessorVisibility(p, property.SetMethod); |
|
if (p.Name == defaultMemberName) { |
|
p.IsIndexer = true; |
|
} |
|
AddParameters(p, property.Parameters); |
|
AddAttributes(CompilationUnit.ProjectContent, p, p.Attributes, property); |
|
Properties.Add(p); |
|
} |
|
} |
|
|
|
static ModifierEnum GetAccessorVisibility(IProperty p, MethodDefinition accessor) |
|
{ |
|
ModifierEnum visibility = ModifierEnum.VisibilityMask & TranslateModifiers(accessor); |
|
if (visibility == (p.Modifiers & ModifierEnum.VisibilityMask)) |
|
return ModifierEnum.None; |
|
else |
|
return visibility; |
|
} |
|
|
|
void AddMethod(MethodDefinition method) |
|
{ |
|
if (IsVisible(method.Attributes)) { |
|
DefaultMethod m = new DefaultMethod(this, method.IsConstructor ? "#ctor" : method.Name); |
|
|
|
if (method.GenericParameters.Count > 0) { |
|
foreach (GenericParameter g in method.GenericParameters) { |
|
m.TypeParameters.Add(new DefaultTypeParameter(m, g.Name, g.Position)); |
|
} |
|
int i = 0; |
|
foreach (GenericParameter g in method.GenericParameters) { |
|
AddConstraintsFromType(m.TypeParameters[i++], g); |
|
} |
|
} |
|
|
|
if (method.IsConstructor) |
|
m.ReturnType = this.DefaultReturnType; |
|
else |
|
m.ReturnType = CreateType(this.ProjectContent, m, method.ReturnType, method.MethodReturnType); |
|
AddAttributes(CompilationUnit.ProjectContent, m, m.Attributes, method); |
|
if (this.ClassType == ClassType.Interface) { |
|
m.Modifiers = ModifierEnum.Public | ModifierEnum.Abstract; |
|
} else { |
|
m.Modifiers = TranslateModifiers(method); |
|
} |
|
AddParameters(m, method.Parameters); |
|
AddExplicitInterfaceImplementations(method.Overrides, m); |
|
ReflectionLayer.ReflectionMethod.ApplySpecialsFromAttributes(m); |
|
Methods.Add(m); |
|
} |
|
} |
|
|
|
void AddExplicitInterfaceImplementations(Collection<MethodReference> overrides, IMember targetMember) |
|
{ |
|
foreach (MethodReference overrideRef in overrides) { |
|
if (overrideRef.Name == targetMember.Name && targetMember.IsPublic) { |
|
continue; // is like implicit interface implementation / normal override |
|
} |
|
targetMember.InterfaceImplementations.Add(new ExplicitInterfaceImplementation( |
|
CreateType(this.ProjectContent, targetMember, overrideRef.DeclaringType), |
|
overrideRef.Name |
|
)); |
|
} |
|
} |
|
|
|
void AddParameters(IMethodOrProperty target, Collection<ParameterDefinition> plist) |
|
{ |
|
foreach (ParameterDefinition par in plist) { |
|
IReturnType pReturnType = CreateType(this.ProjectContent, target, par.ParameterType, par); |
|
DefaultParameter p = new DefaultParameter(par.Name, pReturnType, DomRegion.Empty); |
|
if (par.ParameterType is ByReferenceType) { |
|
if ((par.Attributes & ParameterAttributes.Out) == ParameterAttributes.Out) { |
|
p.Modifiers = ParameterModifiers.Out; |
|
} else { |
|
p.Modifiers = ParameterModifiers.Ref; |
|
} |
|
} else { |
|
p.Modifiers = ParameterModifiers.In; |
|
} |
|
if ((par.Attributes & ParameterAttributes.Optional) == ParameterAttributes.Optional) { |
|
p.Modifiers |= ParameterModifiers.Optional; |
|
} |
|
if (p.ReturnType.IsArrayReturnType) { |
|
foreach (CustomAttribute att in par.CustomAttributes) { |
|
if (att.Constructor.DeclaringType.FullName == typeof(ParamArrayAttribute).FullName) { |
|
p.Modifiers |= ParameterModifiers.Params; |
|
} |
|
} |
|
} |
|
target.Parameters.Add(p); |
|
} |
|
} |
|
|
|
static bool IsVisible(MethodAttributes att) |
|
{ |
|
return ((att & MethodAttributes.Public) == MethodAttributes.Public) |
|
|| ((att & MethodAttributes.Family) == MethodAttributes.Family) |
|
|| ((att & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem); |
|
} |
|
|
|
static bool IsVisible(FieldAttributes att) |
|
{ |
|
return ((att & FieldAttributes.Public) == FieldAttributes.Public) |
|
|| ((att & FieldAttributes.Family) == FieldAttributes.Family) |
|
|| ((att & FieldAttributes.FamORAssem) == FieldAttributes.FamORAssem); |
|
} |
|
|
|
static ModifierEnum TranslateModifiers(MethodDefinition method) |
|
{ |
|
ModifierEnum m = ModifierEnum.None; |
|
|
|
if (method.IsStatic) { |
|
m |= ModifierEnum.Static; |
|
} else { |
|
if (method.IsAbstract) { |
|
m |= ModifierEnum.Abstract; |
|
} else if (method.IsFinal) { |
|
m |= ModifierEnum.Sealed; |
|
} else if (method.Overrides.Count > 0) { |
|
m |= ModifierEnum.Override; |
|
} else if (method.IsVirtual) { |
|
if (method.IsNewSlot) |
|
m |= ModifierEnum.Virtual; |
|
else |
|
m |= ModifierEnum.Override; |
|
} |
|
} |
|
|
|
if ((method.Attributes & MethodAttributes.Public) == MethodAttributes.Public) |
|
m |= ModifierEnum.Public; |
|
else |
|
m |= ModifierEnum.Protected; |
|
|
|
return m; |
|
} |
|
|
|
static ModifierEnum TranslateModifiers(PropertyDefinition property) |
|
{ |
|
return TranslateModifiers(property.GetMethod ?? property.SetMethod); |
|
} |
|
|
|
static ModifierEnum TranslateModifiers(EventDefinition @event) |
|
{ |
|
return TranslateModifiers(@event.AddMethod); |
|
} |
|
|
|
static ModifierEnum TranslateModifiers(FieldDefinition field) |
|
{ |
|
ModifierEnum m = ModifierEnum.None; |
|
|
|
if (field.IsStatic) |
|
m |= ModifierEnum.Static; |
|
|
|
if (field.IsLiteral) |
|
m |= ModifierEnum.Const; |
|
else if (field.IsInitOnly) |
|
m |= ModifierEnum.Readonly; |
|
|
|
if ((field.Attributes & FieldAttributes.Public) == FieldAttributes.Public) |
|
m |= ModifierEnum.Public; |
|
else |
|
m |= ModifierEnum.Protected; |
|
|
|
return m; |
|
} |
|
} |
|
} |
|
}
|
|
|