#region PDFsharp - A .NET library for processing PDF // // Authors: // Stefan Lange // // Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany) // // http://www.pdfsharp.com // http://sourceforge.net/projects/pdfsharp // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. #endregion using System; using System.Diagnostics; using System.Collections.Generic; using System.Reflection; namespace PdfSharp.Pdf { /// /// Holds information about the value of a key in a dictionary. This information is used to create /// and interpret this value. /// internal sealed class KeyDescriptor { /// /// Initializes a new instance of KeyDescriptor from the specified attribute during a KeysMeta /// initializes itself using reflection. /// public KeyDescriptor(KeyInfoAttribute attribute) { _version = attribute.Version; _keyType = attribute.KeyType; _fixedValue = attribute.FixedValue; _objectType = attribute.ObjectType; if (_version == "") _version = "1.0"; } /// /// Gets or sets the PDF version starting with the availability of the described key. /// public string Version { get { return _version; } set { _version = value; } } string _version; public KeyType KeyType { get { return _keyType; } set { _keyType = value; } } KeyType _keyType; public string KeyValue { get { return _keyValue; } set { _keyValue = value; } } string _keyValue; public string FixedValue { get { return _fixedValue; } } readonly string _fixedValue; public Type ObjectType { get { return _objectType; } set { _objectType = value; } } Type _objectType; public bool CanBeIndirect { get { return (_keyType & KeyType.MustNotBeIndirect) == 0; } } /// /// Returns the type of the object to be created as value for the described key. /// public Type GetValueType() { Type type = _objectType; if (type == null) { // If we have no ObjectType specified, use the KeyType enumeration. switch (_keyType & KeyType.TypeMask) { case KeyType.Name: type = typeof(PdfName); break; case KeyType.String: type = typeof(PdfString); break; case KeyType.Boolean: type = typeof(PdfBoolean); break; case KeyType.Integer: type = typeof(PdfInteger); break; case KeyType.Real: type = typeof(PdfReal); break; case KeyType.Date: type = typeof(PdfDate); break; case KeyType.Rectangle: type = typeof(PdfRectangle); break; case KeyType.Array: type = typeof(PdfArray); break; case KeyType.Dictionary: type = typeof(PdfDictionary); break; case KeyType.Stream: type = typeof(PdfDictionary); break; // The following types are not yet used case KeyType.NumberTree: throw new NotImplementedException("KeyType.NumberTree"); case KeyType.NameOrArray: throw new NotImplementedException("KeyType.NameOrArray"); case KeyType.ArrayOrDictionary: throw new NotImplementedException("KeyType.ArrayOrDictionary"); case KeyType.StreamOrArray: throw new NotImplementedException("KeyType.StreamOrArray"); case KeyType.ArrayOrNameOrString: return null; // HACK: Make PdfOutline work //throw new NotImplementedException("KeyType.ArrayOrNameOrString"); default: Debug.Assert(false, "Invalid KeyType: " + _keyType); break; } } return type; } } /// /// Contains meta information about all keys of a PDF dictionary. /// internal class DictionaryMeta { public DictionaryMeta(Type type) { //#if (NETFX_CORE && DEBUG) || CORE // if (type == typeof(PdfPages.Keys)) // { // var x = typeof(PdfPages).GetRuntimeFields(); // var y = typeof(PdfPages).GetTypeInfo().DeclaredFields; // x.GetType(); // y.GetType(); // Debug-Break.Break(); // Test.It(); // } //#endif #if !NETFX_CORE && !UWP FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); foreach (FieldInfo field in fields) { object[] attributes = field.GetCustomAttributes(typeof(KeyInfoAttribute), false); if (attributes.Length == 1) { KeyInfoAttribute attribute = (KeyInfoAttribute)attributes[0]; KeyDescriptor descriptor = new KeyDescriptor(attribute); descriptor.KeyValue = (string)field.GetValue(null); _keyDescriptors[descriptor.KeyValue] = descriptor; } } #else // Rewritten for WinRT. CollectKeyDescriptors(type); //var fields = type.GetRuntimeFields(); // does not work //fields2.GetType(); //foreach (FieldInfo field in fields) //{ // var attributes = field.GetCustomAttributes(typeof(KeyInfoAttribute), false); // foreach (var attribute in attributes) // { // KeyDescriptor descriptor = new KeyDescriptor((KeyInfoAttribute)attribute); // descriptor.KeyValue = (string)field.GetValue(null); // _keyDescriptors[descriptor.KeyValue] = descriptor; // } //} #endif } #if NETFX_CORE || UWP // Background: The function GetRuntimeFields gets constant fields only for the specified type, // not for its base types. So we have to walk recursively through base classes. // The docmentation says full trust for the immediate caller is required for property BaseClass. // TODO: Rewrite this stuff for medium trust. void CollectKeyDescriptors(Type type) { // Get fields of the specified type only. var fields = type.GetTypeInfo().DeclaredFields; foreach (FieldInfo field in fields) { var attributes = field.GetCustomAttributes(typeof(KeyInfoAttribute), false); foreach (var attribute in attributes) { KeyDescriptor descriptor = new KeyDescriptor((KeyInfoAttribute)attribute); descriptor.KeyValue = (string)field.GetValue(null); _keyDescriptors[descriptor.KeyValue] = descriptor; } } type = type.GetTypeInfo().BaseType; if (type != typeof(object) && type != typeof(PdfObject)) CollectKeyDescriptors(type); } #endif #if (NETFX_CORE || CORE) && true_ public class A { public string _a; public const string _ca = "x"; } public class B : A { public string _b; public const string _cb = "x"; void Foo() { var str = A._ca; } } class Test { public static void It() { string s = "Runtime fields of B:"; foreach (var fieldInfo in typeof(B).GetRuntimeFields()) { s += " " + fieldInfo.Name; } Debug.WriteLine(s); s = "Declared fields of B:"; foreach (var fieldInfo in typeof(B).GetTypeInfo().DeclaredFields) { s += " " + fieldInfo.Name; } Debug.WriteLine(s); s = "Runtime fields of PdfPages.Keys:"; foreach (var fieldInfo in typeof(PdfPages.Keys).GetRuntimeFields()) { s += " " + fieldInfo.Name; } Debug.WriteLine(s); } } #endif /// /// Gets the KeyDescriptor of the specified key, or null if no such descriptor exits. /// public KeyDescriptor this[string key] { get { KeyDescriptor keyDescriptor; _keyDescriptors.TryGetValue(key, out keyDescriptor); return keyDescriptor; } } readonly Dictionary _keyDescriptors = new Dictionary(); } }