Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / System / Windows / Markup / ReflectionHelper.cs / 1305600 / ReflectionHelper.cs
//------------------------------------------------------------------------ // // Microsoft Windows Client Platform // Copyright (C) Microsoft Corporation, 2006 // // File: TypeConverterHelper.cs // // Description: Specifies that the whitespace surrounding an element should be trimmed. // //--------------------------------------------------------------------------- using System; using System.IO; using System.Reflection; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Runtime.CompilerServices; using MS.Internal; #if PBTCOMPILER using MS.Utility; namespace MS.Internal.Markup #elif WINDOWS_BASE using MS.Utility; using MS.Internal.WindowsBase; namespace System.Windows.Markup #else namespace System.Xaml #endif { ////// Class that provides helper functions for the parser to reflect on types, properties, /// custom attributes and load assemblies. /// internal static class ReflectionHelper { #region Type ////// Parse and get the type of the passed in string /// internal static Type GetQualifiedType(string typeName) { // ISSUE: we only parse the assembly name and type name // all other Type.GetType() type fragments (version, culture info, pub key token etc) are ignored!!! string[] nameFrags = typeName.Split(new Char[] { ',' }, 2); Type type = null; if (nameFrags.Length == 1) { // treat it as an absolute name type = Type.GetType(nameFrags[0]); } else { if (nameFrags.Length != 2) throw new InvalidOperationException(SR.Get(SRID.QualifiedNameHasWrongFormat, typeName)); Assembly a = null; try { a = LoadAssembly(nameFrags[1].TrimStart(), null); } // ifdef magic to save compiler update. // the fix below is for an FxCop rule about non-CLR exceptions. // however this rule has now been removed. catch (Exception e) // Load throws generic Exceptions, so this can't be made more specific. { if (CriticalExceptions.IsCriticalException(e)) { throw; } else { // If we can't load the assembly, just return null (fall-through). a = null; } } if (a != null) { try { type = a.GetType(nameFrags[0]); // If we can't get the type, just return null (fall-through). } catch (ArgumentException) { a = null; } catch (System.Security.SecurityException) { a = null; } } } return type; } internal static bool IsNullableType(Type type) { return (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>))); } internal static bool IsInternalType(Type type) { Type origType = type; Debug.Assert(null != type, "Type passed to IsInternalType is null"); // If this is an internal nested type or a parent nested public type, walk up the declaring types. while (type.IsNestedAssembly || type.IsNestedFamORAssem || (origType != type && type.IsNestedPublic)) { type = type.DeclaringType; } // If we're on a non-internal nested type, IsNotPublic & IsPublic will both return false. // If we were originally on a nested type and have currently reached a parent // top-level(non nested) type, then it must be top level internal or public type. return type.IsNotPublic || (origType != type && type.IsPublic); } ////// Helper for determine if the type is a public class. /// /// Type to check ///True if type is public internal static bool IsPublicType(Type type) { Debug.Assert(null != type, "Type passed to IsPublicType is null"); // If this is a nested internal type, walk up the declaring types. while (type.IsNestedPublic) { type = type.DeclaringType; } // If we're on a non-public nested type, IsPublic will return false. return type.IsPublic; } // Since System.dll may be loaded in regular load context as well ROL context // we need to get the ROL type from teh real type to compare a type with at compile // time. At run-time, the same type can be used. internal static Type GetSystemType(Type type) { #if PBTCOMPILER Assembly asmSystem = LoadAssembly("System", null); if (asmSystem != null) { type = asmSystem.GetType(type.FullName); } else { type = null; } #endif return type; } #endregion Type #region Attributes internal static string GetTypeConverterAttributeData(Type type, out Type converterType) { bool foundTC = false; return GetCustomAttributeData(type, GetSystemType(typeof(TypeConverterAttribute)), true, ref foundTC, out converterType); } internal static string GetTypeConverterAttributeData(MemberInfo mi, out Type converterType) { return GetCustomAttributeData(mi, GetSystemType(typeof(TypeConverterAttribute)), out converterType); } // Given a ReflectionOnlyLoaded member, returns the value of a metadata attribute of // Type attrType if set on that member. Looks only for attributes that have a ctor with // one parameter that is of Type string or Type. private static string GetCustomAttributeData(MemberInfo mi, Type attrType, out Type typeValue) { IListlist = CustomAttributeData.GetCustomAttributes(mi); string attrValue = GetCustomAttributeData(list, attrType, out typeValue, true, false); return attrValue == null ? string.Empty : attrValue; } #if PBTCOMPILER // Given a ReflectionOnlyLoaded type, returns the value of a metadata attribute of // Type attrType if set on that type. Looks only for attributes that have a ctor with // one parameter that is of Type string. internal static string GetCustomAttributeData(Type t, Type attrType, bool allowZeroArgs) { Type typeValue = null; IList list = CustomAttributeData.GetCustomAttributes(t); return GetCustomAttributeData(list, attrType, out typeValue, false, allowZeroArgs); } #endif // Helper that enumerates a list of CustomAttributeData obtained via ReflectionOnlyLoad, and // looks for a specific attribute of Type attrType. It only looks for attribiutes with a single // value of Type string that is passed in via a ctor. If allowTypeAlso is true, then it looks for // values of typeof(Type) as well. private static string GetCustomAttributeData(IList list, Type attrType, out Type typeValue, bool allowTypeAlso, bool allowZeroArgs) { typeValue = null; string attrValue = null; for (int j = 0; j < list.Count; j++) { attrValue = GetCustomAttributeData(list[j], attrType, out typeValue, allowTypeAlso, false, allowZeroArgs); if (attrValue != null) { break; } } return attrValue; } // Special version of type-based GetCustomAttributeData that does two // additional tasks: // 1) Retrieves the attributes even if it's defined on a base type, and // 2) Distinguishes between "attribute found and said null" and // "no attribute found at all" via the ref bool. internal static string GetCustomAttributeData(Type t, Type attrType, bool allowTypeAlso, ref bool attributeDataFound, out Type typeValue) { typeValue = null; attributeDataFound = false; Type currentType = t; string attributeDataString = null; CustomAttributeData cad; while (currentType != null && !attributeDataFound) { IList list = CustomAttributeData.GetCustomAttributes(currentType); for (int j = 0; j < list.Count && !attributeDataFound; j++) { cad = list[j]; if (cad.Constructor.ReflectedType == attrType) { attributeDataFound = true; attributeDataString = GetCustomAttributeData(cad, attrType, out typeValue, allowTypeAlso, false, false); } } if (!attributeDataFound) { currentType = currentType.BaseType; // object.BaseType is null, used as terminating condition for the while() loop. } } return attributeDataString; } // Helper that inspects a specific CustomAttributeData obtained via ReflectionOnlyLoad, and // returns its value if the Type of the attribiutes matches the passed in attrType. It only // looks for attributes with no values or a single value of Type string that is passed in via // a ctor. If allowTypeAlso is true, then it looks for values of typeof(Type) as well in the // single value case. If noArgs == false and zeroArgsAllowed = true, that means 0 or 1 args // are permissible. private static string GetCustomAttributeData(CustomAttributeData cad, Type attrType, out Type typeValue, bool allowTypeAlso, bool noArgs, bool zeroArgsAllowed) { string attrValue = null; typeValue = null; // get the Constructor info ConstructorInfo cinfo = cad.Constructor; if (cinfo.ReflectedType == attrType) { // typedConstructorArguments (the Attribute constructor arguments) // [MyAttribute("test", Name=Hello)] // "test" is the Constructor Argument IList constructorArguments = cad.ConstructorArguments; if (constructorArguments.Count == 1 && !noArgs) { CustomAttributeTypedArgument tca = constructorArguments[0]; attrValue = tca.Value as String; if (attrValue == null && allowTypeAlso && tca.ArgumentType == typeof(Type)) { typeValue = tca.Value as Type; attrValue = typeValue.AssemblyQualifiedName; } if (attrValue == null) { throw new ArgumentException(SR.Get(SRID.ParserAttributeArgsLow, attrType.Name)); } } else if (constructorArguments.Count == 0) { // zeroArgsAllowed = true for CPA for example. // CPA with no args is valid and would mean that this type is overriding a base CPA if (noArgs || zeroArgsAllowed) { attrValue = string.Empty; } else { throw new ArgumentException(SR.Get(SRID.ParserAttributeArgsLow, attrType.Name)); } } else { throw new ArgumentException(SR.Get(SRID.ParserAttributeArgsHigh, attrType.Name)); } } return attrValue; } #endregion Attributes #region Assembly Loading // // Clean up the cache entry for the given assembly, so that it can be reloaded for the next build cycle. // Usually it is called by MarkupCompiler task. // internal static void ResetCacheForAssembly(string assemblyName) { string assemblyNameLookup = assemblyName.ToUpper(CultureInfo.InvariantCulture); #if PBTCOMPILER _reflectionOnlyLoadedAssembliesHash[assemblyNameLookup] = null; #else _loadedAssembliesHash[assemblyNameLookup] = null; #endif } internal static Assembly LoadAssembly(string assemblyName, string assemblyPath) { #if PBTCOMPILER return ReflectionOnlyLoadAssembly(assemblyName, assemblyPath); #else return LoadAssemblyHelper(assemblyName, assemblyPath); #endif } #if !PBTCOMPILER internal static Assembly GetAlreadyLoadedAssembly(string assemblyNameLookup) { return (Assembly)_loadedAssembliesHash[assemblyNameLookup]; } // Loads the Assembly with the specified name at the specified optional location. // // assemblyName is either short name or full name. // assemblyPath is either full file path or null. // private static Assembly LoadAssemblyHelper(string assemblyGivenName, string assemblyPath) { AssemblyName assemblyName = new AssemblyName(assemblyGivenName); string assemblyShortName = assemblyName.Name; assemblyShortName = assemblyShortName.ToUpper(CultureInfo.InvariantCulture); // Check if the assembly has already been loaded. Assembly retassem = (Assembly)_loadedAssembliesHash[assemblyShortName]; if (retassem != null) { if (assemblyName.Version != null) { AssemblyName cachedName = new AssemblyName(retassem.FullName); if (!AssemblyName.ReferenceMatchesDefinition(assemblyName, cachedName)) { string request = assemblyName.ToString(); string found = cachedName.ToString(); throw new InvalidOperationException(SR.Get(SRID.ParserAssemblyLoadVersionMismatch, request, found)); } } } else { // Check if the current AppDomain has this assembly loaded for some other reason. // If so, then just use that assembly and don't attempt to load another copy of it. // Only do this if no path is provided. if (String.IsNullOrEmpty(assemblyPath)) retassem = SafeSecurityHelper.GetLoadedAssembly(assemblyName); if (retassem == null) { if (!String.IsNullOrEmpty(assemblyPath)) { // assemblyPath is set, Load the assembly from this specified place. // the path must be full file path which contains directory, file name and extension. Debug.Assert(!assemblyPath.EndsWith("\\", StringComparison.Ordinal), "the assembly path should be a full file path containing file extension"); // LoadFile will only override your request only if it is in the GAC retassem = Assembly.LoadFile(assemblyPath); } // // At compile time, the build task should always pass the full path of the referenced assembly, even if it // comes from GAC. But below code snippet can run if parser wants to try loading an assembly w/o a path. // This also makes run-time assembly load consistent with compile-time semantics. else { try { retassem = Assembly.Load(assemblyGivenName); } catch (System.IO.FileNotFoundException) { // This may be a locally defined assembly that has not been created yet. // To support these cases, just set a null assembly and return. This // will fail downstream if it really was an assembly miss. retassem = null; } } } // Cache the assembly if (retassem != null) { _loadedAssembliesHash[assemblyShortName] = retassem; } } return retassem; } private static Hashtable _loadedAssembliesHash = new Hashtable(8); #else // returns true is sourceAssembly declares LocalAssemblyName as a friend internal static bool IsFriendAssembly(Assembly sourceAssembly) { bool isFriend = false; Type typeValue = null; string friendAssemblyName = string.Empty; IList list = CustomAttributeData.GetCustomAttributes(sourceAssembly); for (int j = 0; j < list.Count; j++) { friendAssemblyName = GetCustomAttributeData(list[j], typeof(InternalsVisibleToAttribute), out typeValue, false, false, false); if (friendAssemblyName != null && friendAssemblyName == LocalAssemblyName) { isFriend = true; break; } } return isFriend; } internal static bool IsInternalAllowedOnType(Type type) { return ((LocalAssemblyName == type.Assembly.GetName().Name) || IsFriendAssembly(type.Assembly)); } // The local assembly that contains the baml. internal static string LocalAssemblyName { get { return _localAssemblyName; } set { _localAssemblyName = value; } } private static string _localAssemblyName = string.Empty; internal static bool HasAlreadyReflectionOnlyLoaded(string assemblyNameLookup) { // // If the cache contains an entry for the given assemblyname, and its value is not // null, it marks the assembly has been loaded. // // Since ResetCacheForAssembly( ) just sets "null" in the hashtable for a given assembly // without really removing it, it is possible that an assembly is not reloaded before this // method is called. // Such as for the local-type-ref xaml file compilation, the cache entry for the temporary // assembly is reset to null, but it is not reloaded for MCPass1. // // We don't want to change the behavior of ResetCacheForAssembly( ) at this moment. (Resetting // the value to null without really removing the entry is helpful for the perf) // return (_reflectionOnlyLoadedAssembliesHash.Contains(assemblyNameLookup) && _reflectionOnlyLoadedAssembliesHash[assemblyNameLookup] != null); } internal static Assembly GetAlreadyReflectionOnlyLoadedAssembly(string assemblyNameLookup) { return (Assembly)_reflectionOnlyLoadedAssembliesHash[assemblyNameLookup]; } // // For a given assembly name and its full path, Reflection-Only load the assembly directly // from the file in disk or load the file to memory and then create assembly instance from // memory buffer data. // private static Assembly ReflectionOnlyLoadAssembly(string assemblyGivenName, string fullpath) { Debug.Assert(String.IsNullOrEmpty(assemblyGivenName) == false, "assemblyName should not be empty."); AssemblyName assemblyName = new AssemblyName(assemblyGivenName); string assemblyShortName = assemblyName.Name; assemblyShortName = assemblyShortName.ToUpper(CultureInfo.InvariantCulture); Assembly asm = (Assembly)_reflectionOnlyLoadedAssembliesHash[assemblyShortName]; if (asm != null) { if (assemblyName.Version != null) { AssemblyName cachedName = new AssemblyName(asm.FullName); if (!AssemblyName.ReferenceMatchesDefinition(assemblyName, cachedName)) { string request = assemblyName.ToString(); string found = cachedName.ToString(); throw new InvalidOperationException(SR.Get(SRID.ParserAssemblyLoadVersionMismatch, request, found)); } } } // Reflection doesn't work with mscorlib (different mscorlib's that is). We have problems if // the mscorlib is a dehydrated / asmMeta style reference assembly. // Just use the real MsCorLib we are running on. The alternative is failure. else if ((String.Compare (assemblyShortName, "mscorlib", StringComparison.OrdinalIgnoreCase)==0)) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for(int i=0; i = 0; i--) { if (String.Compare(assemblies[i].GetName().Name, assemblyGivenName, StringComparison.OrdinalIgnoreCase) == 0) { asm = assemblies[i]; break; } } } } } else if (!String.IsNullOrEmpty(fullpath)) { asm = Assembly.ReflectionOnlyLoadFrom(fullpath); } else if (asm == null) { // In the compiler scenario this will be encountered only when there is no path // and parser needs to call this directly to attempt to load an assembly. try { asm = Assembly.ReflectionOnlyLoad(assemblyGivenName); } catch (System.IO.FileNotFoundException) { // This may be a locally defined assembly that has not been created yet. // To support these cases, just set a null assembly and return. This // will fail downstream if it really was an assembly miss. asm = null; } } if (asm != null) { _reflectionOnlyLoadedAssembliesHash[assemblyShortName] = asm; } } return asm; } private static Hashtable _reflectionOnlyLoadedAssembliesHash = new Hashtable(8); // // Copy assembly file from disk to memory, and return the memory buffer. // internal static byte[] GetAssemblyContent(string filepath) { byte[] asmContents = null; using (FileStream fileStream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)) { // FileStream.Read does not support offsets or lengths // larger than int.MaxValue. if (fileStream.Length > int.MaxValue) { return null; } int size = (int)fileStream.Length; asmContents = new byte[size]; if (size > 0) { ReliableRead(fileStream, asmContents, 0, size); } // With using statement, fileStream can always be disposed, // there is no need to put code here to explicitly dispose the // file stream object. } return asmContents; } // // set flag for the assembly to indicate that this assembly should be loaded from memory buffer // instead of file in disk. // // Usually it is called by MarkupCompiler task. // internal static void SetContentLoadForAssembly(string assemblyName) { string assemblyNameLookup = assemblyName.ToUpper(CultureInfo.InvariantCulture); _contentLoadAssembliesHash[assemblyNameLookup] = true; } /// /// Read utility that is guaranteed to return the number of bytes requested /// if they are available. /// /// stream to read from /// buffer to read into /// offset in buffer to write to /// bytes to read ///bytes read ///Normal Stream.Read does not guarantee how many bytes it will /// return. This one does. private static int ReliableRead(Stream stream, byte[] buffer, int offset, int count) { /* Invariant.Assert is not available in PBT Invariant.Assert(stream != null); Invariant.Assert(buffer != null); Invariant.Assert(buffer.Length > 0); Invariant.Assert(offset >= 0); Invariant.Assert(count >= 0); Invariant.Assert(checked(offset + count<= buffer.Length)); */ // let's read the whole block into our buffer int totalBytesRead = 0; while (totalBytesRead < count) { int bytesRead = stream.Read(buffer, offset + totalBytesRead, count - totalBytesRead); if (bytesRead == 0) { break; } totalBytesRead += bytesRead; } return totalBytesRead; } private static Hashtable _contentLoadAssembliesHash = new Hashtable(1); #endif #endregion Assembly Loading } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MenuItem.cs
- DependencyPropertyValueSerializer.cs
- ReadOnlyAttribute.cs
- IsolationInterop.cs
- SqlOuterApplyReducer.cs
- DocumentCollection.cs
- PartialCachingAttribute.cs
- ResourceKey.cs
- ConfigurationManagerInternalFactory.cs
- Pens.cs
- SelectionManager.cs
- CLSCompliantAttribute.cs
- SafeEventLogReadHandle.cs
- RawAppCommandInputReport.cs
- ProjectionCamera.cs
- BinaryEditor.cs
- SafeRightsManagementHandle.cs
- DbParameterCollectionHelper.cs
- DesignerActionList.cs
- ServiceEndpointElement.cs
- SimpleApplicationHost.cs
- NamespaceInfo.cs
- WebServiceErrorEvent.cs
- InputProcessorProfiles.cs
- Rotation3DAnimationBase.cs
- TCEAdapterGenerator.cs
- SHA256Cng.cs
- MessageQueueInstaller.cs
- EntityCommandDefinition.cs
- PriorityQueue.cs
- NavigationWindowAutomationPeer.cs
- PolicyLevel.cs
- DependencyPropertyDescriptor.cs
- ProcessRequestArgs.cs
- WebBrowser.cs
- mongolianshape.cs
- OdbcError.cs
- cookieexception.cs
- KeyNotFoundException.cs
- DataColumnSelectionConverter.cs
- DataGridComponentEditor.cs
- DBBindings.cs
- QueryResultOp.cs
- PagesSection.cs
- ProcessInputEventArgs.cs
- ActivityXRefPropertyEditor.cs
- ControlCollection.cs
- HierarchicalDataSourceControl.cs
- XmlSchemaSimpleTypeUnion.cs
- AdornerLayer.cs
- XmlCharCheckingReader.cs
- SimpleWebHandlerParser.cs
- DelegatingTypeDescriptionProvider.cs
- EventMappingSettingsCollection.cs
- _FtpControlStream.cs
- ObjectSet.cs
- ImageAnimator.cs
- QuarticEase.cs
- InheritanceRules.cs
- DBSqlParserColumnCollection.cs
- SessionIDManager.cs
- WebPartExportVerb.cs
- ActivityCodeDomSerializer.cs
- ScrollItemPattern.cs
- PathNode.cs
- MissingMemberException.cs
- Baml6Assembly.cs
- BindingNavigator.cs
- TemplateBamlTreeBuilder.cs
- SizeValueSerializer.cs
- FilterQueryOptionExpression.cs
- DbProviderServices.cs
- AutoGeneratedField.cs
- xml.cs
- Hashtable.cs
- ListenerSessionConnectionReader.cs
- DataGridColumn.cs
- DayRenderEvent.cs
- Paragraph.cs
- odbcmetadatacolumnnames.cs
- DispatchChannelSink.cs
- Font.cs
- SelectionWordBreaker.cs
- WindowsScroll.cs
- activationcontext.cs
- IdleTimeoutMonitor.cs
- MissingManifestResourceException.cs
- IncomingWebRequestContext.cs
- SqlWriter.cs
- MetadataWorkspace.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- TextDecoration.cs
- ColumnHeader.cs
- AuthorizationContext.cs
- SmtpDigestAuthenticationModule.cs
- ClusterRegistryConfigurationProvider.cs
- BitmapEffectGeneralTransform.cs
- StrokeNodeOperations2.cs
- ViewRendering.cs
- RecordConverter.cs