diff Source/Reflection/Extension/TypeExtension.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Reflection/Extension/TypeExtension.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,305 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using System.Xml.Linq;
+
+namespace BLToolkit.Reflection.Extension
+{
+	public class TypeExtension
+	{
+		#region Consts
+
+		public static class NodeName
+		{
+			public const string Type        = "Type";
+			public const string Member      = "Member";
+			public const string Association = "Association";
+			public const string Relation    = "Relation";
+			public const string MasterIndex = "MasterIndex";
+			public const string SlaveIndex  = "SlaveIndex";
+		}
+
+		public static class AttrName
+		{
+			public const string Name            = "Name";
+			public const string DestinationType = "DestinationType";
+		}
+
+		public static class ValueName
+		{
+			public const char   Delimiter   = '-';
+			public const string Value       = "Value";
+			public const string Type        = "Type";
+			public const string ValueType   = "Value-Type";
+			public const string TypePostfix = "-Type";
+		}
+
+		#endregion
+
+		#region Public Instance Members
+
+		public TypeExtension()
+			: this(new MemberExtensionCollection(), new AttributeNameCollection())
+		{
+		}
+
+		private TypeExtension(
+			MemberExtensionCollection  members,
+			AttributeNameCollection    attributes)
+		{
+			_members    = members;
+			_attributes = attributes;
+		}
+
+		public string Name { get; set; }
+
+		public MemberExtension this[string memberName]
+		{
+			get { return _members[memberName]; }
+		}
+
+		private readonly MemberExtensionCollection _members;
+		public           MemberExtensionCollection  Members
+		{
+			get { return _members; }
+		}
+
+		private readonly AttributeNameCollection _attributes;
+		public           AttributeNameCollection  Attributes
+		{
+			get { return _attributes; }
+		}
+
+		private static readonly TypeExtension _null = new TypeExtension(MemberExtensionCollection.Null, AttributeNameCollection.Null);
+		public           static TypeExtension  Null
+		{
+			get { return _null; }
+		}
+
+		#endregion
+
+		#region Conversion
+
+		public static bool ToBoolean(object value, bool defaultValue)
+		{
+			return value == null? defaultValue: ToBoolean(value);
+		}
+
+		public static bool ToBoolean(object value)
+		{
+			if (value != null)
+			{
+				if (value is bool)
+					return (bool)value;
+
+				var s = value as string;
+
+				if (s != null)
+				{
+					if (s == "1")
+						return true;
+
+					s = s.ToLower();
+
+					if (s == "true" || s == "yes" || s == "on")
+						return true;
+				}
+
+				return Convert.ToBoolean(value);
+			}
+
+			return false;
+		}
+
+		public static object ChangeType(object value, Type type)
+		{
+			if (value == null || type == value.GetType())
+				return value;
+
+			if (type == typeof(string))
+				return value.ToString();
+
+			if (type == typeof(bool))
+				return ToBoolean(value);
+
+			if (type.IsEnum)
+			{
+				if (value is string)
+					return Enum.Parse(type, value.ToString(), false);
+			}
+
+			return Convert.ChangeType(value, type, Thread.CurrentThread.CurrentCulture);
+		}
+
+		#endregion
+
+		#region Public Static Members
+		
+		public static ExtensionList GetExtensions(string xmlFile)
+		{
+			return GetExtensions(xmlFile, Assembly.GetCallingAssembly());
+		}
+
+		public static ExtensionList GetExtensions(string xmlFile, Assembly assembly)
+		{
+			StreamReader streamReader = null;
+
+			try
+			{
+				if (File.Exists(xmlFile))
+				{
+					streamReader = File.OpenText(xmlFile);
+				}
+#if !SILVERLIGHT
+				else
+				{
+					var combinePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, xmlFile);
+
+					if (File.Exists(combinePath))
+						streamReader = File.OpenText(combinePath);
+				}
+#endif
+
+				var embedded = streamReader == null;
+				var stream   = embedded ? assembly.GetManifestResourceStream(xmlFile) : streamReader.BaseStream;
+
+				if (embedded && stream == null)
+				{
+					var names = assembly.GetManifestResourceNames();
+
+					// Prepare file name with a dot to avoid partial name matching.
+					//
+					xmlFile = "." + xmlFile;
+
+					foreach (var name in names)
+					{
+						if (name.EndsWith(xmlFile))
+						{
+							stream = assembly.GetManifestResourceStream(name);
+							break;
+						}
+					}
+				}
+
+				if (stream == null)
+					throw new TypeExtensionException(
+						string.Format("Could not find file '{0}'.", xmlFile));
+
+				using (stream)
+					return GetExtensions(stream);
+			} 
+			finally
+			{
+				if (streamReader != null)
+					streamReader.Close();
+			}
+		}
+
+		public static ExtensionList GetExtensions(Stream xmlDocStream)
+		{
+			var doc = XDocument.Load(new StreamReader(xmlDocStream));
+
+			return CreateTypeInfo(doc);
+		}
+
+		public static TypeExtension GetTypeExtension(Type type, ExtensionList typeExtensions)
+		{
+			var attrs = type.GetCustomAttributes(typeof(TypeExtensionAttribute), true);
+
+			if (attrs != null && attrs.Length != 0)
+			{
+				var attr = (TypeExtensionAttribute)attrs[0];
+
+				if (!string.IsNullOrEmpty(attr.FileName))
+					typeExtensions = GetExtensions(attr.FileName, type.Assembly);
+
+				if (typeExtensions != null && !string.IsNullOrEmpty(attr.TypeName))
+					return typeExtensions[attr.TypeName];
+			}
+
+			return typeExtensions != null? typeExtensions[type]: Null;
+		}
+
+		#endregion
+
+		#region Private Static Members
+
+		private static ExtensionList CreateTypeInfo(XDocument doc)
+		{
+			var list = new ExtensionList();
+
+			foreach (var typeNode in doc.Root.Elements().Where(_ => _.Name.LocalName == NodeName.Type))
+				list.Add(ParseType(typeNode));
+
+			return list;
+		}
+
+		private static TypeExtension ParseType(XElement typeNode)
+		{
+			var ext = new TypeExtension();
+
+			foreach (var attr in typeNode.Attributes())
+			{
+				if (attr.Name.LocalName == AttrName.Name)
+					ext.Name = attr.Value;
+				else
+					ext.Attributes.Add(attr.Name.LocalName, attr.Value);
+			}
+
+			foreach (var node in typeNode.Elements())
+			{
+				if (node.Name.LocalName == NodeName.Member)
+					ext.Members.Add(ParseMember(node));
+				else
+					ext.Attributes.Add(ParseAttribute(node));
+			}
+
+			return ext;
+		}
+
+		private static MemberExtension ParseMember(XElement memberNode)
+		{
+			var ext = new MemberExtension();
+
+			foreach (var attr in memberNode.Attributes())
+			{
+				if (attr.Name.LocalName == AttrName.Name)
+					ext.Name = attr.Value;
+				else
+					ext.Attributes.Add(attr.Name.LocalName, attr.Value);
+			}
+
+			foreach (var node in memberNode.Elements())
+				ext.Attributes.Add(ParseAttribute(node));
+
+			return ext;
+		}
+
+		private static AttributeExtension ParseAttribute(XElement attributeNode)
+		{
+			var ext = new AttributeExtension
+			{
+				Name = attributeNode.Name.LocalName
+			};
+
+			ext.Values.Add(ValueName.Value, attributeNode.Value);
+
+			foreach (var attr in attributeNode.Attributes())
+			{
+				if (attr.Name.LocalName == ValueName.Type)
+					ext.Values.Add(ValueName.ValueType, attr.Value);
+				else
+					ext.Values.Add(attr.Name.LocalName, attr.Value);
+			}
+
+			foreach (var node in attributeNode.Elements())
+				ext.Attributes.Add(ParseAttribute(node));
+
+			return ext;
+		}
+
+		#endregion
+	}
+}