diff --git a/src/.vs/GraphClimber/DesignTimeBuild/.dtbcache.v2 b/src/.vs/GraphClimber/DesignTimeBuild/.dtbcache.v2 new file mode 100644 index 0000000..e2ce513 Binary files /dev/null and b/src/.vs/GraphClimber/DesignTimeBuild/.dtbcache.v2 differ diff --git a/src/GraphClimber.ConsoleApp/Examples/Binary/BinaryFormatter.cs b/src/GraphClimber.ConsoleApp/Examples/Binary/BinaryFormatter.cs new file mode 100644 index 0000000..d20f770 --- /dev/null +++ b/src/GraphClimber.ConsoleApp/Examples/Binary/BinaryFormatter.cs @@ -0,0 +1,46 @@ +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using GraphClimber.Examples; +using GraphClimber.Examples.Binary; + +namespace GraphClimber.ConsoleApp.Examples.Binary +{ + public class BinaryFormatter + { + private readonly IGraphClimber _binaryReader; + private readonly IGraphClimber _binaryWriter; + + public BinaryFormatter() + { + IStateMemberProvider provider = new BinaryStateMemberProvider(new PropertyStateMemberProvider()); + _binaryReader = DefaultGraphClimber.Create(provider); + _binaryWriter = DefaultGraphClimber.Create(provider); + } + + public object Deserialize(IReader reader) + { + return Deserialize(reader); + } + + public T Deserialize(IReader reader) + { + BinaryReaderProcessor processor = new BinaryReaderProcessor(reader); + StrongBox box = new StrongBox(); + _binaryReader.Climb(box, processor); + return box.Value; + } + + public void Serialize(IWriter writer, object graph) + { + Serialize(writer, graph); + } + + public void Serialize(IWriter writer, T graph) + { + BinaryWriterProcessor processor = new BinaryWriterProcessor(writer); + StrongBox box = new StrongBox(){Value = graph}; + _binaryWriter.Climb(box, processor); + } + } +} \ No newline at end of file diff --git a/src/GraphClimber/Examples/Binary/BinaryReaderProcessor.cs b/src/GraphClimber.ConsoleApp/Examples/Binary/BinaryReaderProcessor.cs similarity index 98% rename from src/GraphClimber/Examples/Binary/BinaryReaderProcessor.cs rename to src/GraphClimber.ConsoleApp/Examples/Binary/BinaryReaderProcessor.cs index be93dfb..0c5a947 100644 --- a/src/GraphClimber/Examples/Binary/BinaryReaderProcessor.cs +++ b/src/GraphClimber.ConsoleApp/Examples/Binary/BinaryReaderProcessor.cs @@ -46,7 +46,7 @@ public void ProcessReferenceType(IWriteOnlyExactValueDescriptor descriptor { descriptor.Route( new BinaryStateMember - (new MyCustomStateMember((IReflectionStateMember) descriptor.StateMember, + (new MyCustomStateMember(descriptor.StateMember, type), true, true), @@ -210,7 +210,7 @@ public void ProcessForWriteOnly(IWriteOnlyExactValueDescriptor descripto if (TryReadReferenceType(descriptor, out type)) { string value = _reader.ReadString(); - _objects.Add(value); + //_objects.Add(value); descriptor.Set(value); } } @@ -283,7 +283,7 @@ private int[] ReadIntArray() public void ProcessEnumForWriteOnly<[IsEnum] TEnum, TUnderlying> (IEnumReadWriteExactValueDescriptor descriptor) where TUnderlying : IConvertible - where TEnum : IConvertible + where TEnum : Enum, IConvertible { IStateMember underlying = descriptor.UnderlyingValueStateMember; diff --git a/src/GraphClimber/Examples/Binary/BinaryStateMemberProvider.cs b/src/GraphClimber.ConsoleApp/Examples/Binary/BinaryStateMemberProvider.cs similarity index 74% rename from src/GraphClimber/Examples/Binary/BinaryStateMemberProvider.cs rename to src/GraphClimber.ConsoleApp/Examples/Binary/BinaryStateMemberProvider.cs index e06db47..118a0c2 100644 --- a/src/GraphClimber/Examples/Binary/BinaryStateMemberProvider.cs +++ b/src/GraphClimber.ConsoleApp/Examples/Binary/BinaryStateMemberProvider.cs @@ -18,17 +18,16 @@ public BinaryStateMemberProvider(IStateMemberProvider underlying) public IEnumerable Provide(Type type) { return _underlying.Provide(type) - .Select(x => new BinaryStateMember((IReflectionStateMember)x)); + .Select(x => new BinaryStateMember(x)); } public IStateMember ProvideArrayMember(Type arrayType, int[] indices) { - return new BinaryStateMember((IReflectionStateMember) - _underlying.ProvideArrayMember(arrayType, indices)); + return new BinaryStateMember(_underlying.ProvideArrayMember(arrayType, indices)); } } - public class BinaryStateMember : IReflectionStateMember + public class BinaryStateMember : IStateMember { private readonly IStateMember _stateMember; private readonly bool _knownType; @@ -132,42 +131,6 @@ public bool HeaderHandled get { return _headerHandled; } } - public MemberInfo UnderlyingMemberInfo - { - get - { - var reflectionStateMember = _stateMember as IReflectionStateMember; - if (reflectionStateMember != null) - { - return reflectionStateMember.UnderlyingMemberInfo; - } - - throw new NotImplementedException(); - } - } - - public object GetValue(object owner) - { - var reflectionStateMember = _stateMember as IReflectionStateMember; - if (reflectionStateMember != null) - { - return reflectionStateMember.GetValue(owner); - } - - throw new NotImplementedException(); - } - - public void SetValue(object owner, object value) - { - var reflectionStateMember = _stateMember as IReflectionStateMember; - if (reflectionStateMember != null) - { - reflectionStateMember.SetValue(owner, value); - } - - throw new NotImplementedException(); - } - protected bool Equals(BinaryStateMember other) { return Equals(_stateMember, other._stateMember) && _knownType.Equals(other._knownType); diff --git a/src/GraphClimber/Examples/Binary/BinaryWriterProcessor.cs b/src/GraphClimber.ConsoleApp/Examples/Binary/BinaryWriterProcessor.cs similarity index 98% rename from src/GraphClimber/Examples/Binary/BinaryWriterProcessor.cs rename to src/GraphClimber.ConsoleApp/Examples/Binary/BinaryWriterProcessor.cs index 3f5b1da..de343d0 100644 --- a/src/GraphClimber/Examples/Binary/BinaryWriterProcessor.cs +++ b/src/GraphClimber.ConsoleApp/Examples/Binary/BinaryWriterProcessor.cs @@ -16,12 +16,12 @@ public static class ReadWriteHeader class ReferenceEqualityComparer : IEqualityComparer { - public bool Equals(object x, object y) + bool IEqualityComparer.Equals(object x, object y) { return ReferenceEquals(x, y); } - public int GetHashCode(object obj) + int IEqualityComparer.GetHashCode(object obj) { if (obj == null) { @@ -142,7 +142,7 @@ public void ProcessArray<[IsArray]TArray>(IReadOnlyExactValueDescriptor public void ProcessEnumForReadOnly<[IsEnum]TEnum, TUnderlying> (IReadOnlyEnumExactValueDescriptor descriptor) where TUnderlying : IConvertible - where TEnum : IConvertible + where TEnum : Enum { WriteAssemblyQualifiedNameIfNeeded((BinaryStateMember)descriptor.StateMember, typeof (TEnum)); diff --git a/src/GraphClimber/Examples/Binary/IWriter.cs b/src/GraphClimber.ConsoleApp/Examples/Binary/IWriter.cs similarity index 100% rename from src/GraphClimber/Examples/Binary/IWriter.cs rename to src/GraphClimber.ConsoleApp/Examples/Binary/IWriter.cs diff --git a/src/GraphClimber/Examples/Binary/IsArrayAttribute.cs b/src/GraphClimber.ConsoleApp/Examples/Binary/IsArrayAttribute.cs similarity index 100% rename from src/GraphClimber/Examples/Binary/IsArrayAttribute.cs rename to src/GraphClimber.ConsoleApp/Examples/Binary/IsArrayAttribute.cs diff --git a/src/GraphClimber/Examples/Binary/PositionRestore.cs b/src/GraphClimber.ConsoleApp/Examples/Binary/PositionRestore.cs similarity index 100% rename from src/GraphClimber/Examples/Binary/PositionRestore.cs rename to src/GraphClimber.ConsoleApp/Examples/Binary/PositionRestore.cs diff --git a/src/GraphClimber/Examples/Binary/SuperBinaryWriter.cs b/src/GraphClimber.ConsoleApp/Examples/Binary/SuperBinaryReader.cs similarity index 74% rename from src/GraphClimber/Examples/Binary/SuperBinaryWriter.cs rename to src/GraphClimber.ConsoleApp/Examples/Binary/SuperBinaryReader.cs index 07c731e..a788f9f 100644 --- a/src/GraphClimber/Examples/Binary/SuperBinaryWriter.cs +++ b/src/GraphClimber.ConsoleApp/Examples/Binary/SuperBinaryReader.cs @@ -1,52 +1,10 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace GraphClimber.Examples { - - class SuperBinaryWriter : BinaryWriter - { - private readonly IDictionary _writtenStrings = new Dictionary(); - - protected SuperBinaryWriter() - { - } - - public SuperBinaryWriter(Stream output) : base(output) - { - } - - public SuperBinaryWriter(Stream output, Encoding encoding) : base(output, encoding) - { - } - - public SuperBinaryWriter(Stream output, Encoding encoding, bool leaveOpen) : base(output, encoding, leaveOpen) - { - } - - public override void Write(string value) - { - int id; - if (_writtenStrings.TryGetValue(value, out id)) - { - base.Write((byte)1); - base.Write(id); - } - else - { - _writtenStrings[value] = _writtenStrings.Count; - base.Write((byte)0); - base.Write(value); - } - } - } - - - class SuperBinaryReader : BinaryReader + internal class SuperBinaryReader : BinaryReader { private readonly IList _readStrings = new List(); @@ -64,7 +22,7 @@ public SuperBinaryReader(Stream input, Encoding encoding, bool leaveOpen) : base public override string ReadString() { - var isRead = base.ReadByte(); + byte isRead = base.ReadByte(); if (isRead == 1) { @@ -202,4 +160,4 @@ public override int GetHashCode() return base.GetHashCode(); } } -} +} \ No newline at end of file diff --git a/src/GraphClimber.ConsoleApp/Examples/Binary/SuperBinaryWriter.cs b/src/GraphClimber.ConsoleApp/Examples/Binary/SuperBinaryWriter.cs new file mode 100644 index 0000000..2dd4dd8 --- /dev/null +++ b/src/GraphClimber.ConsoleApp/Examples/Binary/SuperBinaryWriter.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace GraphClimber.Examples +{ + internal class SuperBinaryWriter : BinaryWriter + { + private readonly IDictionary _writtenStrings = new Dictionary(); + + protected SuperBinaryWriter() + { + } + + public SuperBinaryWriter(Stream output) : base(output) + { + } + + public SuperBinaryWriter(Stream output, Encoding encoding) : base(output, encoding) + { + } + + public SuperBinaryWriter(Stream output, Encoding encoding, bool leaveOpen) : base(output, encoding, leaveOpen) + { + } + + public override void Write(string value) + { + int id; + if (_writtenStrings.TryGetValue(value, out id)) + { + base.Write((byte)1); + base.Write(id); + } + else + { + _writtenStrings[value] = _writtenStrings.Count; + base.Write((byte)0); + base.Write(value); + } + } + } +} diff --git a/src/GraphClimber/Examples/Extractor/Extractor.cs b/src/GraphClimber.ConsoleApp/Examples/Extractor/Extractor.cs similarity index 55% rename from src/GraphClimber/Examples/Extractor/Extractor.cs rename to src/GraphClimber.ConsoleApp/Examples/Extractor/Extractor.cs index a911824..350aca4 100644 --- a/src/GraphClimber/Examples/Extractor/Extractor.cs +++ b/src/GraphClimber.ConsoleApp/Examples/Extractor/Extractor.cs @@ -4,19 +4,20 @@ namespace GraphClimber.Examples { public class Extractor { - private readonly SlowGraphClimber> _climber; + private readonly IGraphClimber> _climber; public Extractor() { _climber = - new SlowGraphClimber>(new ReflectionPropertyStateMemberProvider()); + DefaultGraphClimber> + .Create(new PropertyStateMemberProvider()); } public void Extract(object value, Action callback) { ExtractorProcessor processor = new ExtractorProcessor(callback); - _climber.Route(value, processor, false); + _climber.Climb(new Box() {Value = value}, processor); } } } \ No newline at end of file diff --git a/src/GraphClimber/Examples/Extractor/ExtractorProcessor.cs b/src/GraphClimber.ConsoleApp/Examples/Extractor/ExtractorProcessor.cs similarity index 100% rename from src/GraphClimber/Examples/Extractor/ExtractorProcessor.cs rename to src/GraphClimber.ConsoleApp/Examples/Extractor/ExtractorProcessor.cs diff --git a/src/GraphClimber/Examples/MyCustomStateMember.cs b/src/GraphClimber.ConsoleApp/Examples/MyCustomStateMember.cs similarity index 77% rename from src/GraphClimber/Examples/MyCustomStateMember.cs rename to src/GraphClimber.ConsoleApp/Examples/MyCustomStateMember.cs index ff0ef66..7ec607c 100644 --- a/src/GraphClimber/Examples/MyCustomStateMember.cs +++ b/src/GraphClimber.ConsoleApp/Examples/MyCustomStateMember.cs @@ -4,12 +4,12 @@ namespace GraphClimber.Examples { - public class MyCustomStateMember : IReflectionStateMember + public class MyCustomStateMember : IStateMember { - private readonly IReflectionStateMember _underlying; + private readonly IStateMember _underlying; private readonly Type _memberType; - public MyCustomStateMember(IReflectionStateMember underlying, Type memberType) + public MyCustomStateMember(IStateMember underlying, Type memberType) { _underlying = underlying; _memberType = memberType; @@ -63,21 +63,6 @@ public Expression GetSetExpression(Expression obj, Expression value) return _underlying.GetSetExpression(obj, value); } - public MemberInfo UnderlyingMemberInfo - { - get { return _underlying.UnderlyingMemberInfo; } - } - - public object GetValue(object owner) - { - return _underlying.GetValue(owner); - } - - public void SetValue(object owner, object value) - { - _underlying.SetValue(owner, value); - } - protected bool Equals(MyCustomStateMember other) { return Equals(_underlying, other._underlying) && Equals(_memberType, other._memberType); diff --git a/src/GraphClimber/Examples/OldGames.cs b/src/GraphClimber.ConsoleApp/Examples/OldGames.cs similarity index 100% rename from src/GraphClimber/Examples/OldGames.cs rename to src/GraphClimber.ConsoleApp/Examples/OldGames.cs diff --git a/src/GraphClimber/Examples/Store/IStore.cs b/src/GraphClimber.ConsoleApp/Examples/Store/IStore.cs similarity index 100% rename from src/GraphClimber/Examples/Store/IStore.cs rename to src/GraphClimber.ConsoleApp/Examples/Store/IStore.cs diff --git a/src/GraphClimber/Examples/Store/StoreReaderProcessor.cs b/src/GraphClimber.ConsoleApp/Examples/Store/StoreReaderProcessor.cs similarity index 83% rename from src/GraphClimber/Examples/Store/StoreReaderProcessor.cs rename to src/GraphClimber.ConsoleApp/Examples/Store/StoreReaderProcessor.cs index 25e6714..62072ec 100644 --- a/src/GraphClimber/Examples/Store/StoreReaderProcessor.cs +++ b/src/GraphClimber.ConsoleApp/Examples/Store/StoreReaderProcessor.cs @@ -19,20 +19,21 @@ public StoreReaderProcessor(IStore store) public void Process(IWriteOnlyValueDescriptor descriptor) { string type; + + IStore temp = _store; + + _store = _store.GetInner(descriptor.StateMember.Name); + if (_store.TryGet("Type", out type)) { - var value = (T)Activator.CreateInstance(Type.GetType(type)); descriptor.Set(value); - var temp = _store; - _store = _store.GetInner(descriptor.StateMember.Name); - descriptor.Climb(); - - _store = temp; } + + _store = temp; } [ProcessorMethod(Precedence = 99)] @@ -43,17 +44,16 @@ public void ProcessPrimitives<[Primitive]T>(IWriteOnlyExactValueDescriptor de { descriptor.Set(value); } - } [ProcessorMethod] public void Process(IWriteOnlyValueDescriptor descriptor) { - string type; + IStore innerStore = _store.GetInner(descriptor.StateMember.Name); - if (_store.TryGet("Type", out type)) + if (innerStore.TryGet("Type", out string type)) { - descriptor.Route(new MyCustomStateMember((IReflectionStateMember)descriptor.StateMember, Type.GetType(type)), descriptor.Owner, true); + descriptor.Route(new MyCustomStateMember(descriptor.StateMember, Type.GetType(type)), descriptor.Owner, true); } } diff --git a/src/GraphClimber.ConsoleApp/Examples/Store/StoreSerializer.cs b/src/GraphClimber.ConsoleApp/Examples/Store/StoreSerializer.cs new file mode 100644 index 0000000..aa2fe8c --- /dev/null +++ b/src/GraphClimber.ConsoleApp/Examples/Store/StoreSerializer.cs @@ -0,0 +1,33 @@ +namespace GraphClimber.Examples +{ + public class StoreSerializer + { + private readonly IGraphClimber _storeWriterClimber; + private readonly IGraphClimber _storeReaderClimber; + + public StoreSerializer() + { + IStateMemberProvider stateMemberProvider = new PropertyStateMemberProvider(); + _storeWriterClimber = DefaultGraphClimber.Create(stateMemberProvider); + _storeReaderClimber = DefaultGraphClimber.Create(stateMemberProvider); + } + + public void Write(object value, IStore store) + { + Box box = new Box() {Value = value}; + _storeWriterClimber.Climb(box, new StoreWriterProcessor(store)); + } + + public object Read(IStore store) + { + return Read(store); + } + + public T Read(IStore store) + { + Box box = new Box(); + _storeReaderClimber.Climb(box, new StoreReaderProcessor(store)); + return box.Value; + } + } +} \ No newline at end of file diff --git a/src/GraphClimber/Examples/Store/StoreWriterProcessor.cs b/src/GraphClimber.ConsoleApp/Examples/Store/StoreWriterProcessor.cs similarity index 98% rename from src/GraphClimber/Examples/Store/StoreWriterProcessor.cs rename to src/GraphClimber.ConsoleApp/Examples/Store/StoreWriterProcessor.cs index 9479727..f54e809 100644 --- a/src/GraphClimber/Examples/Store/StoreWriterProcessor.cs +++ b/src/GraphClimber.ConsoleApp/Examples/Store/StoreWriterProcessor.cs @@ -1,4 +1,3 @@ -using System.Collections.Concurrent; using System.Collections.Generic; using GraphClimber.ValueDescriptor; @@ -19,11 +18,10 @@ public StoreWriterProcessor(IStore store) public void Process(IReadOnlyValueDescriptor descriptor) { var value = descriptor.Get(); - _store.Set("Type", value.GetType().AssemblyQualifiedName); - var temp = _store; _store = _store.GetInner(descriptor.StateMember.Name); + _store.Set("Type", value.GetType().AssemblyQualifiedName); descriptor.Climb(); diff --git a/src/GraphClimber/Examples/Store/TrivialStore.cs b/src/GraphClimber.ConsoleApp/Examples/Store/TrivialStore.cs similarity index 100% rename from src/GraphClimber/Examples/Store/TrivialStore.cs rename to src/GraphClimber.ConsoleApp/Examples/Store/TrivialStore.cs diff --git a/src/GraphClimber.ConsoleApp/Examples/Xml/Box.cs b/src/GraphClimber.ConsoleApp/Examples/Xml/Box.cs new file mode 100644 index 0000000..3a8b98a --- /dev/null +++ b/src/GraphClimber.ConsoleApp/Examples/Xml/Box.cs @@ -0,0 +1,11 @@ +namespace GraphClimber.Examples +{ + internal class Box : Box + { + public T Value { get; set; } + } + + internal class Box + { + } +} \ No newline at end of file diff --git a/src/GraphClimber/Examples/Xml/XmlReaderProcessor.cs b/src/GraphClimber.ConsoleApp/Examples/Xml/XmlReaderProcessor.cs similarity index 67% rename from src/GraphClimber/Examples/Xml/XmlReaderProcessor.cs rename to src/GraphClimber.ConsoleApp/Examples/Xml/XmlReaderProcessor.cs index a39191c..8cdb163 100644 --- a/src/GraphClimber/Examples/Xml/XmlReaderProcessor.cs +++ b/src/GraphClimber.ConsoleApp/Examples/Xml/XmlReaderProcessor.cs @@ -30,9 +30,16 @@ public void ProcessString(IWriteOnlyExactValueDescriptor descriptor) XElement element = _reader.Element(descriptor.StateMember.Name); - string result = element.Value; + if (element != null) + { + string result = element.Value; - descriptor.Set(result); + descriptor.Set(result); + } + else + { + descriptor.Set(null); + } } [ProcessorMethod(Precedence = 102)] @@ -40,16 +47,23 @@ public void ProcessGeneric(IWriteOnlyValueDescriptor descriptor) { XElement temp = _reader; - _reader = _reader.Element(descriptor.StateMember.Name); - - CreateObject(descriptor); + if (!(descriptor.Owner is Box)) + { + _reader = _reader.Element(descriptor.StateMember.Name); + } - descriptor.Climb(); + if (_reader != null) + { + if (CreateObject(descriptor)) + { + descriptor.Climb(); + } + } _reader = temp; } - private void CreateObject(IWriteOnlyValueDescriptor descriptor) + private bool CreateObject(IWriteOnlyValueDescriptor descriptor) { XAttribute attribute = _reader.Attribute("Type"); @@ -63,13 +77,22 @@ private void CreateObject(IWriteOnlyValueDescriptor descriptor) (T) Activator.CreateInstance(instanceType); descriptor.Set(field); + + return true; } + + return false; } [ProcessorMethod] public void ProcessObject(IWriteOnlyExactValueDescriptor descriptor) { - XElement element = _reader.Element(descriptor.StateMember.Name); + XElement element = _reader; + + if (!(descriptor.Owner is Box)) + { + element = _reader.Element(descriptor.StateMember.Name); + } XAttribute attribute = element.Attribute("Type"); @@ -81,11 +104,9 @@ public void ProcessObject(IWriteOnlyExactValueDescriptor descriptor) // TODO: this will be the route method.. descriptor.Route - (new MyCustomStateMember((IReflectionStateMember) descriptor.StateMember, + (new MyCustomStateMember(descriptor.StateMember, instanceType), descriptor.Owner, true); } } - - } } \ No newline at end of file diff --git a/src/GraphClimber.ConsoleApp/Examples/Xml/XmlSerializer.cs b/src/GraphClimber.ConsoleApp/Examples/Xml/XmlSerializer.cs new file mode 100644 index 0000000..373b9ea --- /dev/null +++ b/src/GraphClimber.ConsoleApp/Examples/Xml/XmlSerializer.cs @@ -0,0 +1,38 @@ +using System.Xml; +using System.Xml.Linq; + +namespace GraphClimber.Examples +{ + public class XmlSerializer + { + private readonly IGraphClimber _writerClimber; + private readonly IGraphClimber _readerClimber; + + public XmlSerializer() + { + IStateMemberProvider memberProvider = new CachingStateMemberProvider(new PropertyStateMemberProvider()); + + _readerClimber = DefaultGraphClimber.Create(memberProvider); + _writerClimber = DefaultGraphClimber.Create(memberProvider); + } + + public void Serialize(T value, XmlWriter writer) + { + XmlWriterProcessor processor = new XmlWriterProcessor(writer); + _writerClimber.Climb(new Box {Value = value}, processor); + } + + public object Deserialize(XElement element) + { + return Deserialize(element); + } + + public T Deserialize(XElement element) + { + XmlReaderProcessor processor = new XmlReaderProcessor(element); + Box box = new Box(); + _readerClimber.Climb(box, processor); + return box.Value; + } + } +} \ No newline at end of file diff --git a/src/GraphClimber/Examples/Xml/XmlWriterProcessor.cs b/src/GraphClimber.ConsoleApp/Examples/Xml/XmlWriterProcessor.cs similarity index 84% rename from src/GraphClimber/Examples/Xml/XmlWriterProcessor.cs rename to src/GraphClimber.ConsoleApp/Examples/Xml/XmlWriterProcessor.cs index 561397e..c9b9ba9 100644 --- a/src/GraphClimber/Examples/Xml/XmlWriterProcessor.cs +++ b/src/GraphClimber.ConsoleApp/Examples/Xml/XmlWriterProcessor.cs @@ -7,12 +7,10 @@ namespace GraphClimber.Examples public class XmlWriterProcessor : INullProcessor { private readonly XmlWriter _writer; - private StringWriter _stringWriter; - public XmlWriterProcessor() + public XmlWriterProcessor(XmlWriter writer) { - _stringWriter = new StringWriter(); - _writer = new XmlTextWriter(_stringWriter); + _writer = writer; } [ProcessorMethod] @@ -63,9 +61,9 @@ private void EndWritePropertyName() public void ProcessNull(IWriteOnlyValueDescriptor descriptor) { - WritePropertyName(descriptor); - _writer.WriteValue("null"); - EndWritePropertyName(); + //WritePropertyName(descriptor); + //_writer.WriteValue("null"); + //EndWritePropertyName(); } } } \ No newline at end of file diff --git a/src/GraphClimber.ConsoleApp/GraphClimber.ConsoleApp.csproj b/src/GraphClimber.ConsoleApp/GraphClimber.ConsoleApp.csproj new file mode 100644 index 0000000..3135c38 --- /dev/null +++ b/src/GraphClimber.ConsoleApp/GraphClimber.ConsoleApp.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/src/GraphClimber.ConsoleApp/Program.cs b/src/GraphClimber.ConsoleApp/Program.cs new file mode 100644 index 0000000..639cdc8 --- /dev/null +++ b/src/GraphClimber.ConsoleApp/Program.cs @@ -0,0 +1,250 @@ +using System; +using System.IO; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Xml; +using System.Xml.Linq; +using GraphClimber.ConsoleApp.Examples.Binary; +using GraphClimber.Examples; +using GraphClimber.Examples.Binary; + +namespace GraphClimber +{ + enum Days + { + Sunday, + Monday, + Tuesday, + Wendensday, + Thursday, + Friday, + Saturday + } + + class SimpleType + { + + + public ValueType SomeValueType { get; set; } + + public string String { get; set; } + + public IConvertible Convertible { get; set; } + + + } + + public class Program + { + private static readonly IStateMemberProvider _stateMemberProvider = new CachingStateMemberProvider(new PropertyStateMemberProvider()); + + public static void DoSomething(StrongBox hello) + { + Console.WriteLine(hello); + } + + + static void Main(string[] args) + { + //ExpressionDebugGames.Play(); + IStore store = new TrivialStore(); + + store.Set("A", 5); + store.GetInner("A").Set("A", 10); + + SerializeDeserializeXML(); + + SerializeDeserializeStore(); + + SerializeDeserializeBinary(); + } + + public static object GetSimpleTypeInstance() + { + return new SimpleType() + { + Convertible = "sadasd", + SomeValueType = Days.Monday, + String = "Hello W0rld" + }; + } + + public class PersonHolder + { + public IPerson A { get; set; } + public IPerson B { get; set; } + + public IPerson C { get; set; } + } + + private static void SerializeDeserializeBinary() + { + BinaryFormatter formatter = new BinaryFormatter(); + + var person = new Box{Value = new [,]{{"abc", "abc", "abc"},{"2","3","4"}}}; + + //object person = GetPerson(); + + //IPerson structure = new Person2() { Age = 25, Surprise = Days.Monday }; + //person = new PersonHolder() { A = structure, B = structure, C = structure }; + + //structure.IncreaseAge(); + + var stream = new MemoryStream(); + IWriter loggingWriter = new LoggingWriter(new CompressingWriter(new BinaryWriterAdapter(new BinaryWriter(stream))), Console.Out); + + formatter.Serialize(loggingWriter, person); + + stream.Position = 0; + IReader loggingReader = new LoggingReader(new DecompressingReader(new BinaryReaderAdapter(new BinaryReader(stream))), Console.Out); + + object deserialized = formatter.Deserialize(loggingReader); + } + + private static void SerializeDeserializeXML() + { + XmlSerializer serializer = new XmlSerializer(); + + var text = + @" + Shani Elharrar + 24 + + 23 + 4 + +"; + + // Writer code: + Person person = new Person() + { + Age = 24, + Name = "Shani Elharrar", + Surprise = new Person() + { + Age = 23, + Name = null, + Surprise = 4 + } + }; + + StringWriter stringWriter = new StringWriter(); + + serializer.Serialize(person, new XmlTextWriter(stringWriter)); + + string xml = stringWriter.ToString(); + + object result = serializer.Deserialize(XElement.Parse(xml)); + } + + public struct MyClass + { + public string Name { get; set; } + } + + class Person + { + public Person() + { + //Children = new List(); + } + + public string Name { get; set; } + + public int Age { get; set; } + + public object Surprise { get; set; } + + public Person Father { get; set; } + + //public IList Children { get; set; } + } + + internal struct Person2 : IPerson + { + public string Name { get; set; } + + public int Age { get; set; } + + public object Surprise { get; set; } + + public object Father { get; set; } + + public Days Day { get; set; } + public void IncreaseAge() + { + Age++; + } + } + + + public static void SerializeDeserializeStore() + { + IStore store = new TrivialStore(); + StoreSerializer serializer = new StoreSerializer(); + + Person person = GetPerson(); + serializer.Write(person, store); + + object copy = serializer.Read(store); + } + + private static Person GetPerson() + { + var ilan = new Person { Age = 26 + 25, Name = "Ilan Zelingher", Surprise = 1 }; + ilan.Surprise = ilan; + return new Person() + { + Age = 26, + Name = "Elad Zelinger", + Father = ilan, + //Children = { new Person() { Name = "Jason"}, new Person() { Name = "Tomerh" }}, + Surprise = new Person() + { + Age = 21, + Name = "Yosi Attias", + Surprise = new MyClass() + { + Name = "YO!" + } + } + }; + } + + private static Person2 GetPerson2() + { + Person2 ilan = new Person2 { Age = 26 + 25, Name = "Ilan Zelingher" }; + + ilan.Surprise = ilan; + return new Person2() + { + Age = 26, + Name = "Elad Zelinger", + Father = ilan, + Day = Days.Tuesday, + Surprise = new Person2() + { + Age = 21, + Name = "Yosi Attias", + Surprise =ilan + //new object[] + //{ + // ilan, ilan, 342, "Hello", + // new int[,]{{1,1},{2,3},{5,8}}, + // new int[]{1,1,2,3,5,8}, + // Days.Saturday + //} + } + }; + + } + } + + public interface IPerson + { + + void IncreaseAge(); + + } +} \ No newline at end of file diff --git a/src/GraphClimber.Debug/ExpressionCompiler/CSharpExpressionDescriber.cs b/src/GraphClimber.Debug/ExpressionCompiler/CSharpExpressionDescriber.cs deleted file mode 100644 index eb83805..0000000 --- a/src/GraphClimber.Debug/ExpressionCompiler/CSharpExpressionDescriber.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.IO; -using System.Linq.Expressions; -using GraphClimber.ExpressionCompiler; -using Mono.Linq.Expressions; - -namespace GraphClimber.Debug.ExpressionCompiler -{ - public class CSharpExpressionDescriber : IExpressionDescriber - { - public static readonly IExpressionDescriber Empty = new CSharpExpressionDescriber(); - - private CSharpExpressionDescriber() - { - - } - - public string Describe(Expression expression) - { - var stringWriter = new StringWriter(); - var csharpWriter = new CSharpWriter(new TextFormatter(stringWriter)); - - csharpWriter.Write(expression); - - return stringWriter.ToString(); - } - } -} \ No newline at end of file diff --git a/src/GraphClimber.Debug/GraphClimber.Debug.csproj b/src/GraphClimber.Debug/GraphClimber.Debug.csproj deleted file mode 100644 index 6ab3bfe..0000000 --- a/src/GraphClimber.Debug/GraphClimber.Debug.csproj +++ /dev/null @@ -1,66 +0,0 @@ - - - - - Debug - AnyCPU - {B003B6BA-6A13-403E-8C1E-D26AE60C58A0} - Library - Properties - GraphClimber.Debug - GraphClimber.Debug - v4.5 - 512 - - - true - full - false - ..\..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - ..\..\bin\Release\ - TRACE - prompt - 4 - true - - - - ..\packages\Mono.Linq.Expressions.1.2.0.0\lib\Mono.Linq.Expressions.dll - - - - - - - - - - - - - - - - {f7fa4635-c6c6-4d82-b344-b737438e1651} - GraphClimber - - - - - - - - \ No newline at end of file diff --git a/src/GraphClimber.Debug/Properties/AssemblyInfo.cs b/src/GraphClimber.Debug/Properties/AssemblyInfo.cs deleted file mode 100644 index 4538988..0000000 --- a/src/GraphClimber.Debug/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("GraphClimber.Debug")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("GraphClimber.Debug")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("8e268eed-bd81-4354-be31-618dd525e6fa")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/GraphClimber.Debug/packages.config b/src/GraphClimber.Debug/packages.config deleted file mode 100644 index 7c2d45b..0000000 --- a/src/GraphClimber.Debug/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/GraphClimber.Tests/GraphClimber.Tests.csproj b/src/GraphClimber.Tests/GraphClimber.Tests.csproj index 34530ae..423f3aa 100644 --- a/src/GraphClimber.Tests/GraphClimber.Tests.csproj +++ b/src/GraphClimber.Tests/GraphClimber.Tests.csproj @@ -1,70 +1,19 @@ - - - + + - Debug - AnyCPU - {99B3FD79-4D4B-4536-9F6B-2F53E86F8603} - Library - Properties - GraphClimber.Tests - GraphClimber.Tests - v4.5 - 512 - 00cceabe + netcoreapp3.1 + + false - - true - full - false - ..\..\bin\Debug\Tests\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - ..\..\bin\Release\Tests\ - TRACE - prompt - 4 - - - - False - ..\packages\NUnit.2.6.4\lib\nunit.framework.dll - - - - - - - - - - - - - - - - + - - {f7fa4635-c6c6-4d82-b344-b737438e1651} - GraphClimber - + + + + - + - - - \ No newline at end of file + + diff --git a/src/GraphClimber.Tests/Properties/AssemblyInfo.cs b/src/GraphClimber.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index c5a809b..0000000 --- a/src/GraphClimber.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("GraphClimber.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("GraphClimber.Tests")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("99b3fd79-4d4b-4536-9f6b-2f53e86f8603")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/GraphClimber.Tests/packages.config b/src/GraphClimber.Tests/packages.config deleted file mode 100644 index c714ef3..0000000 --- a/src/GraphClimber.Tests/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/GraphClimber.sln b/src/GraphClimber.sln index ad77fe3..59ac61a 100644 --- a/src/GraphClimber.sln +++ b/src/GraphClimber.sln @@ -1,13 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30011.22 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphClimber", "GraphClimber\GraphClimber.csproj", "{F7FA4635-C6C6-4D82-B344-B737438E1651}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphClimber", "GraphClimber\GraphClimber.csproj", "{BD78BB49-71BF-4CFA-8DAE-E178623C225D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphClimber.Tests", "GraphClimber.Tests\GraphClimber.Tests.csproj", "{99B3FD79-4D4B-4536-9F6B-2F53E86F8603}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphClimber.Tests", "GraphClimber.Tests\GraphClimber.Tests.csproj", "{1CE9D582-AD82-4D61-B6D1-85AFF6288841}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphClimber.Debug", "GraphClimber.Debug\GraphClimber.Debug.csproj", "{B003B6BA-6A13-403E-8C1E-D26AE60C58A0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphClimber.ConsoleApp", "GraphClimber.ConsoleApp\GraphClimber.ConsoleApp.csproj", "{5686D351-394B-4D2B-A06D-5A3FF1C5108B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,20 +15,23 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F7FA4635-C6C6-4D82-B344-B737438E1651}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7FA4635-C6C6-4D82-B344-B737438E1651}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7FA4635-C6C6-4D82-B344-B737438E1651}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7FA4635-C6C6-4D82-B344-B737438E1651}.Release|Any CPU.Build.0 = Release|Any CPU - {99B3FD79-4D4B-4536-9F6B-2F53E86F8603}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99B3FD79-4D4B-4536-9F6B-2F53E86F8603}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99B3FD79-4D4B-4536-9F6B-2F53E86F8603}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99B3FD79-4D4B-4536-9F6B-2F53E86F8603}.Release|Any CPU.Build.0 = Release|Any CPU - {B003B6BA-6A13-403E-8C1E-D26AE60C58A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B003B6BA-6A13-403E-8C1E-D26AE60C58A0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B003B6BA-6A13-403E-8C1E-D26AE60C58A0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B003B6BA-6A13-403E-8C1E-D26AE60C58A0}.Release|Any CPU.Build.0 = Release|Any CPU + {BD78BB49-71BF-4CFA-8DAE-E178623C225D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD78BB49-71BF-4CFA-8DAE-E178623C225D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD78BB49-71BF-4CFA-8DAE-E178623C225D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD78BB49-71BF-4CFA-8DAE-E178623C225D}.Release|Any CPU.Build.0 = Release|Any CPU + {1CE9D582-AD82-4D61-B6D1-85AFF6288841}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CE9D582-AD82-4D61-B6D1-85AFF6288841}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CE9D582-AD82-4D61-B6D1-85AFF6288841}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CE9D582-AD82-4D61-B6D1-85AFF6288841}.Release|Any CPU.Build.0 = Release|Any CPU + {5686D351-394B-4D2B-A06D-5A3FF1C5108B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5686D351-394B-4D2B-A06D-5A3FF1C5108B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5686D351-394B-4D2B-A06D-5A3FF1C5108B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5686D351-394B-4D2B-A06D-5A3FF1C5108B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8D0DC358-E9C0-426C-BD72-7EFD69F49DB5} + EndGlobalSection EndGlobal diff --git a/src/GraphClimber.sln.DotSettings b/src/GraphClimber.sln.DotSettings index 0a046fc..993cd6d 100644 --- a/src/GraphClimber.sln.DotSettings +++ b/src/GraphClimber.sln.DotSettings @@ -1,3 +1,2 @@  - <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> \ No newline at end of file + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> \ No newline at end of file diff --git a/src/GraphClimber/.vs/GraphClimber/DesignTimeBuild/.dtbcache.v2 b/src/GraphClimber/.vs/GraphClimber/DesignTimeBuild/.dtbcache.v2 new file mode 100644 index 0000000..6d1d6c8 Binary files /dev/null and b/src/GraphClimber/.vs/GraphClimber/DesignTimeBuild/.dtbcache.v2 differ diff --git a/src/GraphClimber/App.config b/src/GraphClimber/App.config deleted file mode 100644 index fe04a3a..0000000 --- a/src/GraphClimber/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/src/GraphClimber/CachingStateMemberProvider.cs b/src/GraphClimber/CachingStateMemberProvider.cs new file mode 100644 index 0000000..7a70bdf --- /dev/null +++ b/src/GraphClimber/CachingStateMemberProvider.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using GraphClimber.ValueDescriptor; + +namespace GraphClimber +{ + public class CachingStateMemberProvider : IStateMemberProvider + { + private readonly IStateMemberProvider _underlying; + + private readonly IDictionary> _cache = new Dictionary>(); + private readonly object _syncRoot = new object(); + + public CachingStateMemberProvider(IStateMemberProvider underlying) + { + _underlying = underlying; + } + + public IEnumerable Provide(Type type) + { + IEnumerable retVal; + if (_cache.TryGetValue(type, out retVal)) + { + return retVal; + } + + lock (_syncRoot) + { + if (!_cache.TryGetValue(type, out retVal)) + { + // ToList() is here to cache yield return methods. + _cache[type] = retVal = _underlying.Provide(type).ToList(); + } + } + + return retVal; + } + + public IStateMember ProvideArrayMember(Type arrayType, int[] indices) + { + return _underlying.ProvideArrayMember(arrayType, indices); + } + } +} \ No newline at end of file diff --git a/src/GraphClimber/DescriptorExtensionMethods.cs b/src/GraphClimber/DescriptorExtensionMethods.cs index d442fe0..f9f10e7 100644 --- a/src/GraphClimber/DescriptorExtensionMethods.cs +++ b/src/GraphClimber/DescriptorExtensionMethods.cs @@ -4,227 +4,227 @@ namespace GraphClimber { - public static class DescriptorExtensionMethods - { - - public static void RouteRuntimeType(this IValueDescriptor descriptor, bool skipSpecialMethod = false) - { - RouteRuntimeType(descriptor, typeof (TRuntime), skipSpecialMethod); - } - - public static void RouteRuntimeType(this IValueDescriptor descriptor, Type runtimeType, - bool skipSpecialMethod = false) - { - descriptor.Route(descriptor.StateMember, runtimeType, descriptor.Owner, skipSpecialMethod); - } - - public static void RouteMemberType(this IValueDescriptor descriptor, bool skipSpecialMethod = false) - { - var memberType = typeof(TMember); - RouteMemberType(descriptor, memberType, skipSpecialMethod); - } - - public static void RouteMemberType(IValueDescriptor descriptor, Type memberType, bool skipSpecialMethod = false) - { - descriptor.Route(descriptor.StateMember.WithMemberType(memberType), memberType, descriptor.Owner, skipSpecialMethod); - } - - public static void RouteMemberType(this IValueDescriptor descriptor, string name, bool skipSpecialMethod = false) - { - var memberType = typeof(TMember); - RouteMemberType(descriptor, name, memberType, skipSpecialMethod); - } - - public static void RouteMemberType(IValueDescriptor descriptor, string name, Type memberType, - bool skipSpecialMethod = false) - { - descriptor.Route(descriptor.StateMember.WithMemberType(memberType).WithName(name), memberType, descriptor.Owner, - skipSpecialMethod); - } - } - - public static class StateMemberExtensions - { - - public static IStateMember WithName(this IStateMember stateMember, string name) - { - return new NamedStateMember(stateMember, name); - } - - public static IStateMember WithMemberType(this IStateMember stateMember, Type memberType) - { - return new MemberTypeStateMember(stateMember, memberType); - } - - private class NamedStateMember : IStateMember - { - private readonly IStateMember _underlying; - private readonly string _name; - - public NamedStateMember(IStateMember underlying, string name) - { - _underlying = underlying; - _name = name; - } - - public string Name - { - get { return _name; } - } - - public Type OwnerType - { - get { return _underlying.OwnerType; } - } - - public Type MemberType - { - get { return _underlying.MemberType; } - } - - public bool CanRead - { - get { return _underlying.CanRead; } - } - - public bool CanWrite - { - get { return _underlying.CanWrite; } - } - - public Expression GetGetExpression(Expression obj) - { - return _underlying.GetGetExpression(obj); - } - - public Expression GetSetExpression(Expression obj, Expression value) - { - return _underlying.GetSetExpression(obj, value); - } - - public bool IsArrayElement - { - get { return _underlying.IsArrayElement; } - } - - public int[] ElementIndex - { - get { return _underlying.ElementIndex; } - } - - protected bool Equals(NamedStateMember other) - { - return Equals(_underlying, other._underlying) && string.Equals(_name, other._name); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((NamedStateMember) obj); - } - - public override int GetHashCode() - { - unchecked - { - return ((_underlying != null ? _underlying.GetHashCode() : 0)*397) ^ (_name != null ? _name.GetHashCode() : 0); - } - } - } - - private class MemberTypeStateMember : IStateMember, IReflectionStateMember - { - private readonly IStateMember _underlying; - private readonly Type _memberType; - - public MemberTypeStateMember(IStateMember underlying, Type memberType) - { - _underlying = underlying; - _memberType = memberType; - } - - public string Name - { - get { return _underlying.Name; } - } - - public Type OwnerType - { - get { return _underlying.OwnerType; } - } - - public Type MemberType - { - get { return _memberType; } - } - - public bool CanRead - { - get { return _underlying.CanRead; } - } - - public bool CanWrite - { - get { return _underlying.CanWrite; } - } - - public Expression GetGetExpression(Expression obj) - { - return _underlying.GetGetExpression(obj); - } - - public Expression GetSetExpression(Expression obj, Expression value) - { - return _underlying.GetSetExpression(obj, value); - } - - public bool IsArrayElement - { - get { return _underlying.IsArrayElement; } - } - - public int[] ElementIndex - { - get { return _underlying.ElementIndex; } - } - - protected bool Equals(MemberTypeStateMember other) - { - return Equals(_underlying, other._underlying) && Equals(_memberType, other._memberType); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((MemberTypeStateMember) obj); - } - - public override int GetHashCode() - { - unchecked - { - return ((_underlying != null ? _underlying.GetHashCode() : 0)*397) ^ (_memberType != null ? _memberType.GetHashCode() : 0); - } - } - - public MemberInfo UnderlyingMemberInfo - { - get { return ((IReflectionStateMember)_underlying).UnderlyingMemberInfo; } - } - - public object GetValue(object owner) - { - throw new NotImplementedException(); - } - - public void SetValue(object owner, object value) - { - throw new NotImplementedException(); - } - } - } + //public static class DescriptorExtensionMethods + //{ + + // public static void RouteRuntimeType(this IValueDescriptor descriptor, bool skipSpecialMethod = false) + // { + // RouteRuntimeType(descriptor, typeof (TRuntime), skipSpecialMethod); + // } + + // public static void RouteRuntimeType(this IValueDescriptor descriptor, Type runtimeType, + // bool skipSpecialMethod = false) + // { + // descriptor.Route(descriptor.StateMember, runtimeType, descriptor.Owner, skipSpecialMethod); + // } + + // public static void RouteMemberType(this IValueDescriptor descriptor, bool skipSpecialMethod = false) + // { + // var memberType = typeof(TMember); + // RouteMemberType(descriptor, memberType, skipSpecialMethod); + // } + + // public static void RouteMemberType(IValueDescriptor descriptor, Type memberType, bool skipSpecialMethod = false) + // { + // descriptor.Route(descriptor.StateMember.WithMemberType(memberType), memberType, descriptor.Owner, skipSpecialMethod); + // } + + // public static void RouteMemberType(this IValueDescriptor descriptor, string name, bool skipSpecialMethod = false) + // { + // var memberType = typeof(TMember); + // RouteMemberType(descriptor, name, memberType, skipSpecialMethod); + // } + + // public static void RouteMemberType(IValueDescriptor descriptor, string name, Type memberType, + // bool skipSpecialMethod = false) + // { + // descriptor.Route(descriptor.StateMember.WithMemberType(memberType).WithName(name), memberType, descriptor.Owner, + // skipSpecialMethod); + // } + //} + + //public static class StateMemberExtensions + //{ + + // public static IStateMember WithName(this IStateMember stateMember, string name) + // { + // return new NamedStateMember(stateMember, name); + // } + + // public static IStateMember WithMemberType(this IStateMember stateMember, Type memberType) + // { + // return new MemberTypeStateMember(stateMember, memberType); + // } + + // private class NamedStateMember : IStateMember + // { + // private readonly IStateMember _underlying; + // private readonly string _name; + + // public NamedStateMember(IStateMember underlying, string name) + // { + // _underlying = underlying; + // _name = name; + // } + + // public string Name + // { + // get { return _name; } + // } + + // public Type OwnerType + // { + // get { return _underlying.OwnerType; } + // } + + // public Type MemberType + // { + // get { return _underlying.MemberType; } + // } + + // public bool CanRead + // { + // get { return _underlying.CanRead; } + // } + + // public bool CanWrite + // { + // get { return _underlying.CanWrite; } + // } + + // public Expression GetGetExpression(Expression obj) + // { + // return _underlying.GetGetExpression(obj); + // } + + // public Expression GetSetExpression(Expression obj, Expression value) + // { + // return _underlying.GetSetExpression(obj, value); + // } + + // public bool IsArrayElement + // { + // get { return _underlying.IsArrayElement; } + // } + + // public int[] ElementIndex + // { + // get { return _underlying.ElementIndex; } + // } + + // protected bool Equals(NamedStateMember other) + // { + // return Equals(_underlying, other._underlying) && string.Equals(_name, other._name); + // } + + // public override bool Equals(object obj) + // { + // if (ReferenceEquals(null, obj)) return false; + // if (ReferenceEquals(this, obj)) return true; + // if (obj.GetType() != this.GetType()) return false; + // return Equals((NamedStateMember) obj); + // } + + // public override int GetHashCode() + // { + // unchecked + // { + // return ((_underlying != null ? _underlying.GetHashCode() : 0)*397) ^ (_name != null ? _name.GetHashCode() : 0); + // } + // } + // } + + // private class MemberTypeStateMember : IStateMember, IReflectionStateMember + // { + // private readonly IStateMember _underlying; + // private readonly Type _memberType; + + // public MemberTypeStateMember(IStateMember underlying, Type memberType) + // { + // _underlying = underlying; + // _memberType = memberType; + // } + + // public string Name + // { + // get { return _underlying.Name; } + // } + + // public Type OwnerType + // { + // get { return _underlying.OwnerType; } + // } + + // public Type MemberType + // { + // get { return _memberType; } + // } + + // public bool CanRead + // { + // get { return _underlying.CanRead; } + // } + + // public bool CanWrite + // { + // get { return _underlying.CanWrite; } + // } + + // public Expression GetGetExpression(Expression obj) + // { + // return _underlying.GetGetExpression(obj); + // } + + // public Expression GetSetExpression(Expression obj, Expression value) + // { + // return _underlying.GetSetExpression(obj, value); + // } + + // public bool IsArrayElement + // { + // get { return _underlying.IsArrayElement; } + // } + + // public int[] ElementIndex + // { + // get { return _underlying.ElementIndex; } + // } + + // protected bool Equals(MemberTypeStateMember other) + // { + // return Equals(_underlying, other._underlying) && Equals(_memberType, other._memberType); + // } + + // public override bool Equals(object obj) + // { + // if (ReferenceEquals(null, obj)) return false; + // if (ReferenceEquals(this, obj)) return true; + // if (obj.GetType() != this.GetType()) return false; + // return Equals((MemberTypeStateMember) obj); + // } + + // public override int GetHashCode() + // { + // unchecked + // { + // return ((_underlying != null ? _underlying.GetHashCode() : 0)*397) ^ (_memberType != null ? _memberType.GetHashCode() : 0); + // } + // } + + // public MemberInfo UnderlyingMemberInfo + // { + // get { return ((IReflectionStateMember)_underlying).UnderlyingMemberInfo; } + // } + + // public object GetValue(object owner) + // { + // throw new NotImplementedException(); + // } + + // public void SetValue(object owner, object value) + // { + // throw new NotImplementedException(); + // } + // } + //} } diff --git a/src/GraphClimber/ExpressionCompiler/AccessPrivateFieldVisitor.cs b/src/GraphClimber/ExpressionCompiler/AccessPrivateFieldVisitor.cs deleted file mode 100644 index 5667553..0000000 --- a/src/GraphClimber/ExpressionCompiler/AccessPrivateFieldVisitor.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.Diagnostics; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using GraphClimber.ExpressionCompiler.Extensions; - -namespace GraphClimber.ExpressionCompiler -{ - /// - /// An - /// that mutates expressions that calls non public members (Fields, Properties or Methods) - /// to use "reflection" accessors. - /// - /// This is usually used on expressions that compiled to dynamic assemblies, Because - /// in this type of compilation, They cannot access non public members. - /// - public class AccessPrivateFieldVisitor : ExpressionVisitor - { - private const BindingFlags BindingFlags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public; - - public static readonly ExpressionVisitor Empty = new AccessPrivateFieldVisitor(); - - /// - /// Gets the field value from the given instance - /// - /// - /// - /// The instance to get the field value from, Or null for static fields - /// - [DebuggerNonUserCode] - public static object GetFieldValue(string assemblyQualifiedName, string fieldName, object instance) - { - return GetType(assemblyQualifiedName).GetField(fieldName, BindingFlags).GetValue(instance); - } - - /// - /// Gets the property value from the given instance - /// - /// - /// - /// The instance to get the property value from, Or null for static properties - /// - [DebuggerNonUserCode] - public static object GetPropertyValue(string assemblyQualifiedName, string propertyName, object instance) - { - return GetType(assemblyQualifiedName).GetProperty(propertyName, BindingFlags).GetValue(instance); - } - - /// - /// Calls the method on the given instance and returns the value from the method - /// - /// - /// - /// - /// The instance to call the method on, Or null for static methods - /// - /// - [DebuggerNonUserCode] - public static object CallMethod(string assemblyQualifiedName, string methodName, string[] genericArgumentTypes, - object instance, - params object[] parameters) - { - var methodInfo = GetType(assemblyQualifiedName).GetMethod(methodName, BindingFlags); - - if (methodInfo.ContainsGenericParameters) - { - methodInfo = methodInfo.MakeGenericMethod(genericArgumentTypes.Select(GetType).ToArray()); - } - - return methodInfo.Invoke(instance, parameters); - } - - /// - /// Gets the given type or throws exception in case - /// it's not found. - /// - /// - /// - private static Type GetType(string assemblyQualifiedName) - { - var returnValue = Type.GetType(assemblyQualifiedName); - - if (returnValue == null) - { - throw new NullReferenceException( - string.Format("Could not load type with assembly qualified name : '{0}', Exception thrown by '{1}'.", - assemblyQualifiedName, typeof (AccessPrivateFieldVisitor))); - } - - return returnValue; - } - - protected override Expression VisitMethodCall(MethodCallExpression node) - { - if (!node.Method.IsPublic) - { - // In case of static methods, instance should be null. - var reflectionInstance = node.Object ?? ExpressionExtensions.Null; - - // In case of generic method, - // we create an array of the assembly qualified names of the generic arguments. - var genericArgumentTypes = node.Method.IsGenericMethod - ? (Expression)Expression.NewArrayInit(typeof(string), node.Method.GetGenericArguments().Select(t => t.AssemblyQualifiedName.Constant())) - : ExpressionExtensions.Null; - - return - Expression.Call(null, typeof(AccessPrivateFieldVisitor).GetMethod("CallMethod"), - node.Method.DeclaringType.AssemblyQualifiedName.Constant(), - node.Method.Name.Constant(), - genericArgumentTypes, - reflectionInstance, - Expression.NewArrayInit(typeof(object), node.Arguments)).Convert(node.Type); - } - - return base.VisitMethodCall(node); - } - - protected override Expression VisitMember(MemberExpression node) - { - var fieldInfo = node.Member as FieldInfo; - if (fieldInfo != null) - { - return VisitFieldMemberExpression(node, fieldInfo); - } - - var propertyInfo = node.Member as PropertyInfo; - if (propertyInfo != null) - { - return VisitPropertyMemberExpression(node, propertyInfo); - } - - - return base.VisitMember(node); - } - - private static Expression VisitFieldMemberExpression(MemberExpression node, FieldInfo fieldInfo) - { - FieldAttributes fieldAttributes = fieldInfo.Attributes; - - bool isPrivateField = fieldAttributes.HasFlag(FieldAttributes.Private) || - fieldAttributes.HasFlag(FieldAttributes.PrivateScope); - - if (isPrivateField) - { - var argument = node.Expression ?? ExpressionExtensions.Null; - - return Expression.Call(null, - typeof (AccessPrivateFieldVisitor).GetMethod("GetFieldValue"), - fieldInfo.DeclaringType.AssemblyQualifiedName.Constant(), - fieldInfo.Name.Constant(), - argument).Convert(node.Type); - } - - return node; - } - - private static Expression VisitPropertyMemberExpression(MemberExpression node, PropertyInfo propertyInfo) - { - bool isPrivate = - new[] {propertyInfo.GetGetMethod(true), propertyInfo.GetSetMethod(true)}.Where(m => m != null) - .Select(m => m.Attributes) - .Any(m => m.HasFlag(MethodAttributes.Private)); - - if (isPrivate) - { - var argument = node.Expression.Convert() ?? ExpressionExtensions.Null; - - return Expression.Call(null, - typeof (AccessPrivateFieldVisitor).GetMethod("GetPropertyValue"), - propertyInfo.DeclaringType.AssemblyQualifiedName.Constant(), - propertyInfo.Name.Constant(), - argument).Convert(node.Type); - } - - return node; - } - } -} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionCompiler/DebugExpressionCompiler.cs b/src/GraphClimber/ExpressionCompiler/DebugExpressionCompiler.cs deleted file mode 100644 index 0a911a8..0000000 --- a/src/GraphClimber/ExpressionCompiler/DebugExpressionCompiler.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.CompilerServices; - -namespace GraphClimber.ExpressionCompiler -{ - /// - /// An - /// That compiles methods into dynamic assemblies. - /// - /// Also it, Writes the expression description to temporary file and allows - /// debugging with normal IDE (e.g Visual Studio). - /// - public class DebugExpressionCompiler : IExpressionCompiler - { - private readonly IExpressionDescriber _expressionDescriber; - - public DebugExpressionCompiler(IExpressionDescriber expressionDescriber) - { - _expressionDescriber = expressionDescriber; - } - - public TDelegate Compile(Expression expression) - { - var dynamicType = GetDynamicTypeBuilder(); - var dynamicMethod = dynamicType.DefineMethod(expression.Name, MethodAttributes.Public | MethodAttributes.Static); - - var tempFileName = Path.GetTempFileName(); - - File.AppendAllText(tempFileName, _expressionDescriber.Describe(expression)); - - var symbolDocument = Expression.SymbolDocument(tempFileName); - - var finalExpression = MutateLambdaExpression(expression, symbolDocument); - - CompileToMethod(finalExpression, dynamicMethod); - - var newType = dynamicType.CreateType(); - - return (TDelegate)(object)Delegate.CreateDelegate(typeof(TDelegate), newType.GetMethod(dynamicMethod.Name)); - } - - private static void CompileToMethod(Expression expression, - MethodBuilder dynamicMethod) - { - var gen = DebugInfoGenerator.CreatePdbGenerator(); - expression.CompileToMethod(dynamicMethod, gen); - } - - private Expression MutateLambdaExpression(Expression expression, - SymbolDocumentInfo symbolDocument) - { - Expression returnValue = GetVisitors(expression, symbolDocument) - .Aggregate(expression, (current, visitor) => visitor.Visit(current)); - - return (Expression)returnValue; - } - - private static TypeBuilder GetDynamicTypeBuilder() - { - var dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("GraphClimber.RuntimeGenerated"), - AssemblyBuilderAccess.RunAndSave); - var dynamicModule = dynamicAssembly.DefineDynamicModule("DynamicModule", true); - var dynamicType = dynamicModule.DefineType("GeneratedType", TypeAttributes.Public); - return dynamicType; - } - - private ExpressionVisitor[] GetVisitors(Expression expression, SymbolDocumentInfo symbolDocument) - { - return new[] { new DebugExpressionVistor(symbolDocument, expression, _expressionDescriber), NonTrivialConstantVisitor.Empty, AccessPrivateFieldVisitor.Empty }; - } - } -} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionCompiler/DebugExpressionVistor.cs b/src/GraphClimber/ExpressionCompiler/DebugExpressionVistor.cs deleted file mode 100644 index b1ec51e..0000000 --- a/src/GraphClimber/ExpressionCompiler/DebugExpressionVistor.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; - -namespace GraphClimber.ExpressionCompiler -{ - public class DebugExpressionVistor : ExpressionVisitor - { - private static readonly ICollection _untouchedExpressionTypes = new[] { typeof(ParameterExpression), typeof(ConstantExpression) }; - private static readonly ICollection _unsymboledExpressionTypes = new[] { typeof(BlockExpression), typeof(LambdaExpression), typeof(LoopExpression) }; - - private static readonly string[] _newLineSeperator = { Environment.NewLine }; - - private readonly SymbolDocumentInfo _symbolDocumentInfo; - private readonly IExpressionDescriber _expressionDescriber; - private readonly string _initialDebugView; - private int _currentIndex; - - public DebugExpressionVistor(SymbolDocumentInfo symbolDocumentInfo, Expression initialExpression, IExpressionDescriber expressionDescriber) - { - _symbolDocumentInfo = symbolDocumentInfo; - _expressionDescriber = expressionDescriber; - - _initialDebugView = _expressionDescriber.Describe(initialExpression); - } - - private bool ContainsType(IEnumerable types, object instance) - { - var type = instance.GetType(); - - return types.Any(currentType => currentType.IsAssignableFrom(type)); - } - - public override Expression Visit(Expression node) - { - if (node == null) - { - return null; - } - - // Untouched remains as they are - if (ContainsType(_untouchedExpressionTypes, node)) - { - return node; - } - - // Unsymboled is not symboled, the node children are. - if (ContainsType(_unsymboledExpressionTypes, node)) - { - return base.Visit(node); - } - - Range range = GetCurrentExpressionRange(node); - - // Still not sure why I have so many plus one. - Expression debugInfoExpression = Expression.DebugInfo(_symbolDocumentInfo, - range.Start.Line + 1, - range.Start.Column + 1, - range.End.Line + 1, - range.End.Column + 1); - - Expression innerExpression = base.Visit(node); - - return Expression.Block(debugInfoExpression, innerExpression); - } - - private Range GetCurrentExpressionRange(Expression node) - { - string debugView = _expressionDescriber.Describe(node); - string[] debugViewLines = debugView.Split(_newLineSeperator, StringSplitOptions.RemoveEmptyEntries); - string firstDebugViewLine = debugViewLines.First(); - - var newIndex = _initialDebugView.IndexOf(firstDebugViewLine, _currentIndex, StringComparison.Ordinal); - _currentIndex = newIndex; - - Position start = _initialDebugView.GetPosition(_currentIndex); - int spacing = _initialDebugView.Split(_newLineSeperator, StringSplitOptions.None)[start.Line].IndexOfNot(' '); - - Position end = _initialDebugView.GetPosition(_currentIndex + debugView.Length + (debugViewLines.Length - 1) * spacing); - - return new Range(start, end); - } - - private struct Range - { - private readonly T _start; - private readonly T _end; - - public Range(T start, T end) - { - _start = start; - _end = end; - } - - public T Start - { - get { return _start; } - } - - public T End - { - get { return _end; } - } - } - } -} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionCompiler/DebugViewExpressionDescriber.cs b/src/GraphClimber/ExpressionCompiler/DebugViewExpressionDescriber.cs deleted file mode 100644 index a0889c8..0000000 --- a/src/GraphClimber/ExpressionCompiler/DebugViewExpressionDescriber.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Linq.Expressions; -using System.Reflection; - -namespace GraphClimber.ExpressionCompiler -{ - /// - /// Implementation of - /// using the property "DebugView" of the expressions. - /// - /// This may not work if microsoft/mono changes the implementation - /// of "DebugView". - /// - public class DebugViewExpressionDescriber : IExpressionDescriber - { - public static readonly IExpressionDescriber Empty = new DebugViewExpressionDescriber(); - - private static readonly PropertyInfo _debugView = typeof(Expression).GetProperty("DebugView", BindingFlags.NonPublic | BindingFlags.Instance); - - /// - /// Private C'tor, Please use property to get the instance of . - /// - private DebugViewExpressionDescriber() - { - - } - - private static string GetDebugView(Expression expression) - { - return (string) _debugView.GetValue(expression); - } - - public string Describe(Expression expression) - { - return GetDebugView(expression); - } - } -} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionCompiler/IExpressionCompiler.cs b/src/GraphClimber/ExpressionCompiler/IExpressionCompiler.cs deleted file mode 100644 index e8fcdc6..0000000 --- a/src/GraphClimber/ExpressionCompiler/IExpressionCompiler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Linq.Expressions; - -namespace GraphClimber.ExpressionCompiler -{ - public interface IExpressionCompiler - { - TDelegate Compile(Expression expression); - } -} diff --git a/src/GraphClimber/ExpressionCompiler/IExpressionDescriber.cs b/src/GraphClimber/ExpressionCompiler/IExpressionDescriber.cs deleted file mode 100644 index a4fae01..0000000 --- a/src/GraphClimber/ExpressionCompiler/IExpressionDescriber.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Linq.Expressions; - -namespace GraphClimber.ExpressionCompiler -{ - /// - /// Represents an object that can transform expressions to their describing strings. - /// - /// E.g, Transform expression to C# code. - /// - public interface IExpressionDescriber - { - - string Describe(Expression expression); - - } -} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionCompiler/NonTrivialConstantVisitor.cs b/src/GraphClimber/ExpressionCompiler/NonTrivialConstantVisitor.cs deleted file mode 100644 index d70d6fd..0000000 --- a/src/GraphClimber/ExpressionCompiler/NonTrivialConstantVisitor.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; -using GraphClimber.ExpressionCompiler.Extensions; - -namespace GraphClimber.ExpressionCompiler -{ - public class NonTrivialConstantVisitor : ExpressionVisitor - { - private static readonly MethodInfo _getMethodInfo = typeof (NonTrivialConstantVisitor).GetMethod("Get", BindingFlags.Static | BindingFlags.Public); - - private static readonly IList _objects = new List(); - private static readonly object _syncRoot = new object(); - - public static readonly ExpressionVisitor Empty = new NonTrivialConstantVisitor(); - - private NonTrivialConstantVisitor() - { - - } - - public static object Get(int number) - { - return _objects[number]; - } - - public static int Add(object value) - { - lock (_syncRoot) - { - int objectNumber = _objects.Count; - - _objects.Add(value); - - return objectNumber; - } - } - - protected override Expression VisitConstant(ConstantExpression node) - { - if (node.Type.IsPrimitive || node.Type == typeof(string)) - { - return base.VisitConstant(node); - } - - // RuntimeType is internal, using Type instead. - if (node.Type.FullName == "System.RuntimeType") - { - return Expression.Constant(node.Value, typeof (Type)); - } - - int objectNumber = Add(node.Value); - - return Expression.Call(_getMethodInfo, objectNumber.Constant()).Convert(node.Type); - } - } -} diff --git a/src/GraphClimber/ExpressionCompiler/StringExtensions.cs b/src/GraphClimber/ExpressionCompiler/StringExtensions.cs deleted file mode 100644 index 7e95a4d..0000000 --- a/src/GraphClimber/ExpressionCompiler/StringExtensions.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; - -namespace GraphClimber.ExpressionCompiler -{ - public static class StringExtensions - { - - /// - /// Gets the cursor position (Column, Line) of the given index in the given string. - /// - /// - /// - /// - public static Position GetPosition(this string str, int index) - { - var column = index; - var newLineIndex = str.IndexOf(Environment.NewLine, StringComparison.Ordinal); - var newLines = 0; - - while (newLineIndex != -1 && newLineIndex < index) - { - newLines++; - column = index - newLineIndex - Environment.NewLine.Length; - newLineIndex = str.IndexOf(Environment.NewLine, newLineIndex + 1, StringComparison.Ordinal); - } - - return new Position(newLines, column); - } - - public static int IndexOfNot(this string str, char chr) - { - for (int i = 0; i < str.Length; i++) - { - if (str[i] != chr) - { - return i; - } - } - - return -1; - } - - public static string FirstLowerCase(this string str) - { - return str.Substring(0, 1).ToLowerInvariant() + str.Substring(1); - } - - } - - /// - /// Represents a position inside a string - /// - public struct Position - { - private readonly int _line; - private readonly int _column; - - public Position(int line, int column) - { - _line = line; - _column = column; - } - - /// - /// Gets the line of the position - /// - public int Line - { - get - { - return _line; - } - } - - /// - /// Gets the column of the position - /// - public int Column - { - get - { - return _column; - } - } - - } -} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionCompiler/TrivialExpressionCompiler.cs b/src/GraphClimber/ExpressionCompiler/TrivialExpressionCompiler.cs deleted file mode 100644 index f17733b..0000000 --- a/src/GraphClimber/ExpressionCompiler/TrivialExpressionCompiler.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; - -namespace GraphClimber.ExpressionCompiler -{ - public class TrivialExpressionCompiler : IExpressionCompiler - { - public TDelegate Compile(Expression expression) - { - return expression.Compile(); - } - } - - public class FallbackExpressionCompiler : IExpressionCompiler - { - private readonly IExpressionCompiler[] _compilers; - - public FallbackExpressionCompiler(params IExpressionCompiler[] compilers) - { - _compilers = compilers; - } - - public TDelegate Compile(Expression expression) - { - IList exceptions = null; - - foreach (var compiler in _compilers) - { - try - { - return compiler.Compile(expression); - } - catch (Exception e) - { - exceptions = exceptions ?? new List(); - exceptions.Add(e); - } - } - - throw new AggregateException("Could not compile expression with any of the compilers given. Exceptions are collected.", exceptions); - } - } -} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionCompiler/Extensions/ExpressionExtensions.cs b/src/GraphClimber/ExpressionExtensions.cs similarity index 77% rename from src/GraphClimber/ExpressionCompiler/Extensions/ExpressionExtensions.cs rename to src/GraphClimber/ExpressionExtensions.cs index e400a15..d2a1ecb 100644 --- a/src/GraphClimber/ExpressionCompiler/Extensions/ExpressionExtensions.cs +++ b/src/GraphClimber/ExpressionExtensions.cs @@ -1,12 +1,8 @@ using System; using System.Linq.Expressions; -namespace GraphClimber.ExpressionCompiler.Extensions +namespace GraphClimber { - /// - /// Provides extension methods to create - /// expressions easier. - /// internal static class ExpressionExtensions { @@ -62,7 +58,8 @@ public static Expression Convert(this Expression expression, Type newType) var unaryExpression = expression as UnaryExpression; if (unaryExpression != null) { - if (unaryExpression.NodeType == ExpressionType.Convert) + if (unaryExpression.NodeType == ExpressionType.Convert && + !unaryExpression.IsCustomConversion()) { return Convert(unaryExpression.Operand, newType); } @@ -71,5 +68,18 @@ public static Expression Convert(this Expression expression, Type newType) return Expression.Convert(expression, newType); } + private static bool IsCustomConversion(this UnaryExpression unaryExpression) + { + Type conversionType = unaryExpression.Type; + Type originalType = unaryExpression.Operand.Type; + + return !(conversionType.IsAssignableFrom(originalType) || + originalType.IsAssignableFrom(conversionType)); + } + + public static string FirstLowerCase(this string str) + { + return str.Substring(0, 1).ToLowerInvariant() + str.Substring(1); + } } -} +} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionImplementation/AccessorFactory.cs b/src/GraphClimber/ExpressionImplementation/AccessorFactory.cs index 2632027..e9d33a6 100644 --- a/src/GraphClimber/ExpressionImplementation/AccessorFactory.cs +++ b/src/GraphClimber/ExpressionImplementation/AccessorFactory.cs @@ -1,21 +1,9 @@ using System; using System.Linq.Expressions; -using System.Reflection; -using System.Reflection.Emit; -using GraphClimber.ExpressionCompiler; -using GraphClimber.ExpressionCompiler.Extensions; - namespace GraphClimber { internal class AccessorFactory : IAccessorFactory { - private readonly IExpressionCompiler _compiler; - - public AccessorFactory(IExpressionCompiler compiler) - { - _compiler = compiler; - } - public Action GetSetter(IStateMember member) { ParameterExpression instance = Expression.Parameter(typeof(object)); @@ -27,7 +15,7 @@ public Action GetSetter(IStateMember member) "Setter_" + member.Name, new[] {instance, value}); - return _compiler.Compile(lambda); + return lambda.Compile(); } public Func GetGetter(IStateMember member) @@ -40,7 +28,7 @@ public Func GetGetter(IStateMember member) "Getter_" + member.Name, new[] {instance}); - return _compiler.Compile(lambda); + return lambda.Compile(); } private static Expression GetGetterExpression(IStateMember member, Expression instance) diff --git a/src/GraphClimber/ExpressionImplementation/ArrayStateMember.cs b/src/GraphClimber/ExpressionImplementation/ArrayStateMember.cs new file mode 100644 index 0000000..f730739 --- /dev/null +++ b/src/GraphClimber/ExpressionImplementation/ArrayStateMember.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace GraphClimber +{ + internal class ArrayStateMember : IStateMember + { + private readonly Type _arrayType; + private readonly Type _arrayElementType; + private readonly int[] _indices; + + public ArrayStateMember(Type arrayType, Type arrayElementType, int[] indices) + { + _arrayType = arrayType; + _arrayElementType = arrayElementType; + _indices = indices; + } + + public string Name + { + get + { + return string.Format("[{0}]", + string.Join(", ", _indices)); + } + } + + public Type OwnerType + { + get + { + return _arrayType; + } + } + + public Type MemberType + { + get + { + return _arrayElementType; + } + } + + public bool CanRead + { + get { return true; } + } + + public bool CanWrite + { + get { return true; } + } + + public Expression GetGetExpression(Expression obj) + { + Expression getExpression = ArrayAccess(obj); + return getExpression; + } + + private Expression ArrayAccess(Expression obj) + { + ConstantExpression array = Expression.Constant(_indices, typeof(int[])); + + IEnumerable indices = + Enumerable.Range(0, _indices.Length) + .Select(x => Expression.ArrayIndex(array, + Expression.Constant(x))); + return Expression.ArrayAccess(obj.Convert(this._arrayType), indices); + } + + public Expression GetSetExpression(Expression obj, Expression value) + { + Expression arrayAccess = ArrayAccess(obj); + return Expression.Assign(arrayAccess, value); + } + + public bool IsArrayElement + { + get + { + return true; + } + } + + public int[] ElementIndex + { + get + { + return _indices; + } + } + } +} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionImplementation/ClimbDelegateFactory.cs b/src/GraphClimber/ExpressionImplementation/ClimbDelegateFactory.cs index ee3bbe7..37bed6b 100644 --- a/src/GraphClimber/ExpressionImplementation/ClimbDelegateFactory.cs +++ b/src/GraphClimber/ExpressionImplementation/ClimbDelegateFactory.cs @@ -2,9 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Reflection; -using GraphClimber.ExpressionCompiler; -using GraphClimber.ExpressionCompiler.Extensions; namespace GraphClimber { @@ -14,16 +11,14 @@ internal class ClimbDelegateFactory private readonly IStateMemberProvider _stateMemberProvider; private readonly IMethodMapper _methodMapper; private readonly ClimbStore _climbStore; - private readonly IExpressionCompiler _compiler; private readonly CallProcessMutator _mutator; - public ClimbDelegateFactory(Type processorType, IStateMemberProvider stateMemberProvider, IMethodMapper methodMapper, ClimbStore climbStore, IExpressionCompiler compiler) + public ClimbDelegateFactory(Type processorType, IStateMemberProvider stateMemberProvider, IMethodMapper methodMapper, ClimbStore climbStore) { _processorType = processorType; _stateMemberProvider = stateMemberProvider; _methodMapper = methodMapper; _climbStore = climbStore; - _compiler = compiler; _mutator = new CallProcessMutator(_processorType, _methodMapper); } @@ -56,16 +51,7 @@ private ClimbDelegate CreateReferenceDelegate(Type runtimeType) foreach (IStateMember member in members) { - DescriptorWriter writer = new DescriptorWriter(_climbStore); - - DescriptorVariable descriptor = - writer.GetDescriptor(castedProcessor, owner, member, member.MemberType); - - Expression callProcessor = - _mutator.GetExpression(castedProcessor, owner, member, descriptor.Reference); - - descriptorVariables.Add(descriptor.Reference); - expressions.Add(descriptor.Declaration); + Expression callProcessor = CallProcessor(castedProcessor, owner, member, descriptorVariables, expressions); expressions.Add(callProcessor); } @@ -77,11 +63,32 @@ private ClimbDelegate CreateReferenceDelegate(Type runtimeType) "Climb_" + runtimeType.Name, new[] {processor, value}); - ClimbDelegate result = _compiler.Compile(lambda); + ClimbDelegate result = lambda.Compile(); return result; } + private Expression CallProcessor + (Expression castedProcessor, + Expression owner, + IStateMember member, + List methodVariables, + List methodAssignments) + { + DescriptorWriter writer = new DescriptorWriter(_climbStore); + + DescriptorVariable descriptor = + writer.GetDescriptor(castedProcessor, owner, member, member.MemberType); + + Expression callProcessor = + _mutator.GetExpression(castedProcessor, owner, member, descriptor.Reference); + + methodVariables.Add(descriptor.Reference); + methodAssignments.Add(descriptor.Declaration); + + return callProcessor; + } + private ClimbDelegate CreateArrayDelegate(Type runtimeType) { @@ -93,56 +100,92 @@ private ClimbDelegate CreateArrayDelegate(Type runtimeType) var ranks = runtimeType.GetArrayRank(); + int[] indices = new int[ranks]; + var member = _stateMemberProvider.ProvideArrayMember(runtimeType, indices); + + List variables = new List(); + List assignments = new List(); + + Expression callExpression = + CallProcessor(castedProcessor, owner, member, variables, assignments); + + var loop = LoopArrayBounds(ranks, owner, Expression.Constant(indices), callExpression, variables, assignments); + + BlockExpression climbBody = + Expression.Block(variables, + assignments.Concat(new[] {loop})); + + Expression> lambda = + Expression.Lambda>(climbBody, + "Climb_" + runtimeType.Name, + new[] { processor, value }); + + ClimbDelegate result = lambda.Compile(); + + return result; + } + + private static Expression LoopArrayBounds + (int ranks, + Expression owner, + Expression stateMemberArray, + Expression callExpression, + List parameterExpressions, + List assignments) + { var rankParameters = - Enumerable.Range(0, ranks).Select(r => Expression.Variable(typeof (int), "rank_" + r)).ToList(); + Enumerable.Range(0, ranks).Select(r => Expression.Variable(typeof(int), "rank_" + r)).ToList(); var upperBoundParameters = - Enumerable.Range(0, ranks).Select(r => Expression.Variable(typeof (int), "upper_" + r)).ToList(); - - var assignRankParameters = new Expression[ranks]; - var assignUpperParameters = new Expression[ranks]; - + Enumerable.Range(0, ranks).Select(r => Expression.Variable(typeof(int), "upper_" + r)).ToList(); - Expression callExpression = Expression.Empty(); // TODO : Complete. for (int rank = ranks - 1; rank >= 0; rank--) { // Create a for loop from lowerBound to upperBound? - var breakTarget = Expression.Label("break"); - var continueTarget = Expression.Label("continue"); + var breakTarget = Expression.Label("break" + rank); + var continueTarget = Expression.Label("continue" + rank); - assignRankParameters[rank] = Expression.Assign(rankParameters[rank], - Expression.Call(owner, "GetLowerBound", null, Expression.Constant(rank))); + // i_k = array.GetLowerBound(k) + var currentLoopVariableAssignment = + Expression.Assign(rankParameters[rank], + Expression.Call(owner, "GetLowerBound", null, + Expression.Constant(rank))); - assignUpperParameters[rank] = Expression.Assign(upperBoundParameters[rank], - Expression.Call(owner, "GetUpperBound", null, Expression.Constant(rank))); + // length_k = array.GetUpperBound(k) + var currentUpperBoundAssignment = Expression.Assign(upperBoundParameters[rank], + Expression.Call(owner, "GetUpperBound", null, + Expression.Constant(rank))); - var loopBody = - Expression.Block( - Expression.IfThen( - Expression.Equal(upperBoundParameters[rank], rankParameters[rank]), - Expression.Goto(breakTarget)), - callExpression, - Expression.PostIncrementAssign(rankParameters[rank]), - Expression.Goto(continueTarget)); - - callExpression = Expression.Loop(loopBody, breakTarget, continueTarget); - } + assignments.Add(currentUpperBoundAssignment); - BlockExpression climbBody = - Expression.Block(rankParameters.Concat(upperBoundParameters), - assignRankParameters.Concat(assignUpperParameters).Concat(new[] {callExpression})); + Expression binaryExpression = Expression.ArrayAccess(stateMemberArray, + Expression.Constant(rank)); + Expression setIndexer = + Expression.Assign(binaryExpression, + rankParameters[rank]); - Expression> lambda = - Expression.Lambda>(climbBody, - "Climb_" + runtimeType.Name, - new[] { processor, value }); + Expression setIndexerAndCallMethod = + Expression.Block(setIndexer, callExpression); - ClimbDelegate result = _compiler.Compile(lambda); + var loopBody = + Expression.Block( + Expression.IfThen( + Expression.GreaterThan(rankParameters[rank], upperBoundParameters[rank]), + Expression.Goto(breakTarget)), + setIndexerAndCallMethod, + Expression.PostIncrementAssign(rankParameters[rank]), + Expression.Goto(continueTarget)); + + callExpression = + Expression.Block(currentLoopVariableAssignment, + Expression.Loop(loopBody, breakTarget, continueTarget)); + } - return result; + parameterExpressions.AddRange(rankParameters); + parameterExpressions.AddRange(upperBoundParameters); - throw new NotImplementedException("CreateArrayDelegate is not implemented"); + return callExpression; } } } \ No newline at end of file diff --git a/src/GraphClimber/ExpressionImplementation/ClimbStore.cs b/src/GraphClimber/ExpressionImplementation/ClimbStore.cs index 73cd7dd..15de967 100644 --- a/src/GraphClimber/ExpressionImplementation/ClimbStore.cs +++ b/src/GraphClimber/ExpressionImplementation/ClimbStore.cs @@ -1,5 +1,4 @@ using System; -using GraphClimber.ExpressionCompiler; namespace GraphClimber { @@ -16,11 +15,11 @@ internal class ClimbStore : IClimbStore private readonly RouteDelegateFactory _routeFactory; private readonly ClimbDelegateFactory _climbFactory; - public ClimbStore(Type processorType, IStateMemberProvider stateMemberProvider, IMethodMapper methodMapper, IExpressionCompiler compiler) + public ClimbStore(Type processorType, IStateMemberProvider stateMemberProvider, IMethodMapper methodMapper) { - _accessorFactory = new AccessorFactory(compiler); - _routeFactory = new RouteDelegateFactory(processorType, methodMapper, this, compiler); - _climbFactory = new ClimbDelegateFactory(processorType, stateMemberProvider, methodMapper, this, compiler); + _accessorFactory = new AccessorFactory(); + _routeFactory = new RouteDelegateFactory(processorType, methodMapper, this); + _climbFactory = new ClimbDelegateFactory(processorType, stateMemberProvider, methodMapper, this); } public Action GetSetter(IStateMember member) diff --git a/src/GraphClimber/ExpressionImplementation/DefaultGraphClimber.cs b/src/GraphClimber/ExpressionImplementation/DefaultGraphClimber.cs index 210c0b5..eaeaf1e 100644 --- a/src/GraphClimber/ExpressionImplementation/DefaultGraphClimber.cs +++ b/src/GraphClimber/ExpressionImplementation/DefaultGraphClimber.cs @@ -1,14 +1,12 @@ -using GraphClimber.ExpressionCompiler; - -namespace GraphClimber +namespace GraphClimber { - class DefaultGraphClimber : IGraphClimber + public class DefaultGraphClimber : IGraphClimber { private readonly ClimbStore _climbStore; - public DefaultGraphClimber(IStateMemberProvider stateMemberProvider, IMethodMapper methodMapper, IExpressionCompiler expressionCompiler ) + private DefaultGraphClimber(IStateMemberProvider stateMemberProvider, IMethodMapper methodMapper) { - _climbStore = new ClimbStore(typeof (TProcessor), stateMemberProvider, methodMapper, expressionCompiler); + _climbStore = new ClimbStore(typeof (TProcessor), stateMemberProvider, methodMapper); } public void Climb(object parent, TProcessor processor) @@ -25,8 +23,7 @@ public static IGraphClimber Create(IStateMemberProvider stateMemberP { return new DefaultGraphClimber( stateMemberProvider, - new MethodMapper(), - new TrivialExpressionCompiler()); + new MethodMapper()); } } } diff --git a/src/GraphClimber/ExpressionImplementation/DelegateCache/ClimbDelegateCache.cs b/src/GraphClimber/ExpressionImplementation/DelegateCache/ClimbDelegateCache.cs index 3b100fb..3d20e9e 100644 --- a/src/GraphClimber/ExpressionImplementation/DelegateCache/ClimbDelegateCache.cs +++ b/src/GraphClimber/ExpressionImplementation/DelegateCache/ClimbDelegateCache.cs @@ -4,12 +4,12 @@ namespace GraphClimber { internal class ClimbDelegateCache : DelegateCache> { - public new TDelegate Get(Type fieldType, Type runtimeType) + public TDelegate Get(Type fieldType, Type runtimeType) { return base.Get(Tuple.Create(fieldType, runtimeType)); } - public new TDelegate GetOrAdd(Type fieldType, Type runtimeType, Func factory) + public TDelegate GetOrAdd(Type fieldType, Type runtimeType, Func factory) { Func, TDelegate> tupleFactory = tuple => factory(tuple.Item1, tuple.Item2); diff --git a/src/GraphClimber/ExpressionImplementation/DescriptorVariable.cs b/src/GraphClimber/ExpressionImplementation/DescriptorVariable.cs index 2ed46fa..9b159bc 100644 --- a/src/GraphClimber/ExpressionImplementation/DescriptorVariable.cs +++ b/src/GraphClimber/ExpressionImplementation/DescriptorVariable.cs @@ -2,8 +2,6 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; -using GraphClimber.ExpressionCompiler; -using GraphClimber.ExpressionCompiler.Extensions; namespace GraphClimber { diff --git a/src/GraphClimber/ExpressionImplementation/EnumConvert.cs b/src/GraphClimber/ExpressionImplementation/EnumConvert.cs new file mode 100644 index 0000000..48df970 --- /dev/null +++ b/src/GraphClimber/ExpressionImplementation/EnumConvert.cs @@ -0,0 +1,34 @@ +using System; +using System.Linq.Expressions; + +namespace GraphClimber +{ + internal class EnumConvert + { + public static readonly Func ToUnderlying = GetToUnderlying(); + public static readonly Func ToEnum = GetToEnum(); + + private static Func GetToUnderlying() + { + return GetConvert(); + } + + private static Func GetToEnum() + { + return GetConvert(); + } + + + private static Func GetConvert() + { + var parameter = Expression.Parameter(typeof(TSource), "value"); + + Expression> lambda = + Expression.Lambda> + (Expression.Convert(parameter, typeof(TTarget)), + parameter); + + return lambda.Compile(); + } + } +} \ No newline at end of file diff --git a/src/GraphClimber/ExpressionImplementation/EnumReadWriteDescriptor.cs b/src/GraphClimber/ExpressionImplementation/EnumReadWriteDescriptor.cs index 5735b56..6259ce9 100644 --- a/src/GraphClimber/ExpressionImplementation/EnumReadWriteDescriptor.cs +++ b/src/GraphClimber/ExpressionImplementation/EnumReadWriteDescriptor.cs @@ -5,7 +5,7 @@ namespace GraphClimber internal class EnumReadOnlyDescriptor : ReadOnlyDescriptor, IReadOnlyEnumExactValueDescriptor - where TRuntime : TField, IConvertible + where TRuntime : Enum, TField where TUnderlying : IConvertible { // TRuntime is Enum! @@ -29,7 +29,7 @@ internal class EnumWriteOnlyDescriptor : WriteOnlyDescriptor, IWriteOnlyEnumExactValueDescriptor where TUnderlying : IConvertible - where TField : IConvertible + where TField : Enum { // TField is Enum! public EnumWriteOnlyDescriptor(object processor, @@ -48,7 +48,7 @@ public void SetUnderlying(TUnderlying value) } public interface IEnumReadWriteExactValueDescriptor : IReadOnlyEnumExactValueDescriptor, IWriteOnlyEnumExactValueDescriptor - where TEnum : IConvertible + where TEnum : Enum, IConvertible where TUnderlying : IConvertible { } @@ -56,7 +56,7 @@ public interface IEnumReadWriteExactValueDescriptor : IReadO internal class EnumReadWriteDescriptor : ReadWriteDescriptor, IEnumReadWriteExactValueDescriptor - where TRuntime : TField, IConvertible + where TRuntime : Enum, TField where TUnderlying : IConvertible { // TRuntime is Enum! diff --git a/src/GraphClimber/ExpressionImplementation/EnumUnderlyingStateMember.cs b/src/GraphClimber/ExpressionImplementation/EnumUnderlyingStateMember.cs index 92bf935..3318c70 100644 --- a/src/GraphClimber/ExpressionImplementation/EnumUnderlyingStateMember.cs +++ b/src/GraphClimber/ExpressionImplementation/EnumUnderlyingStateMember.cs @@ -1,11 +1,10 @@ using System; using System.Linq.Expressions; using System.Reflection; -using GraphClimber.ExpressionCompiler.Extensions; namespace GraphClimber { - internal class EnumUnderlyingStateMember : IStateMember, IReflectionStateMember + internal class EnumUnderlyingStateMember : IStateMember { private readonly IStateMember _underlying; @@ -76,46 +75,5 @@ public override int GetHashCode() { return (_underlying != null ? _underlying.GetHashCode() : 0); } - - public MemberInfo UnderlyingMemberInfo - { - get - { - var underlying = _underlying as IReflectionStateMember; - - if (underlying != null) - { - return underlying.UnderlyingMemberInfo; - } - - throw new NotImplementedException(); - } - } - - public object GetValue(object owner) - { - var underlying = _underlying as IReflectionStateMember; - - if (underlying != null) - { - return underlying.GetValue(owner); - } - - throw new NotImplementedException(); - } - - public void SetValue(object owner, object value) - { - var underlying = _underlying as IReflectionStateMember; - - if (underlying != null) - { - underlying.SetValue(owner, value); - } - else - { - throw new NotImplementedException(); - } - } } } \ No newline at end of file diff --git a/src/GraphClimber/ExpressionImplementation/Mutators/NullProcessorMutator.cs b/src/GraphClimber/ExpressionImplementation/Mutators/NullProcessorMutator.cs index bb48da9..90dd9a7 100644 --- a/src/GraphClimber/ExpressionImplementation/Mutators/NullProcessorMutator.cs +++ b/src/GraphClimber/ExpressionImplementation/Mutators/NullProcessorMutator.cs @@ -1,7 +1,6 @@ using System; using System.Linq.Expressions; using System.Reflection; -using GraphClimber.ExpressionCompiler.Extensions; namespace GraphClimber { diff --git a/src/GraphClimber/ExpressionImplementation/Mutators/PolymorphismMutator.cs b/src/GraphClimber/ExpressionImplementation/Mutators/PolymorphismMutator.cs index 55b44a6..8fa6ae8 100644 --- a/src/GraphClimber/ExpressionImplementation/Mutators/PolymorphismMutator.cs +++ b/src/GraphClimber/ExpressionImplementation/Mutators/PolymorphismMutator.cs @@ -1,9 +1,6 @@ using System; -using System.Linq; using System.Linq.Expressions; using System.Reflection; -using GraphClimber.ExpressionCompiler; -using GraphClimber.ExpressionCompiler.Extensions; namespace GraphClimber { diff --git a/src/GraphClimber/ExpressionImplementation/Mutators/RevisitedMutator.cs b/src/GraphClimber/ExpressionImplementation/Mutators/RevisitedMutator.cs index 01fb68f..92afa29 100644 --- a/src/GraphClimber/ExpressionImplementation/Mutators/RevisitedMutator.cs +++ b/src/GraphClimber/ExpressionImplementation/Mutators/RevisitedMutator.cs @@ -1,7 +1,6 @@ using System; using System.Linq.Expressions; using System.Reflection; -using GraphClimber.ExpressionCompiler.Extensions; namespace GraphClimber { diff --git a/src/GraphClimber/ExpressionImplementation/PropertyStateMember.cs b/src/GraphClimber/ExpressionImplementation/PropertyStateMember.cs index 3d7ae61..e7d242c 100644 --- a/src/GraphClimber/ExpressionImplementation/PropertyStateMember.cs +++ b/src/GraphClimber/ExpressionImplementation/PropertyStateMember.cs @@ -1,11 +1,10 @@ using System; using System.Linq.Expressions; using System.Reflection; -using GraphClimber.ExpressionCompiler.Extensions; namespace GraphClimber { - internal class PropertyStateMember : IReflectionStateMember + internal class PropertyStateMember : IStateMember { private readonly PropertyInfo _property; private static readonly int[] EmptyIndex = new int[0]; diff --git a/src/GraphClimber/ExpressionImplementation/PropertyStateMemberProvider.cs b/src/GraphClimber/ExpressionImplementation/PropertyStateMemberProvider.cs index 370da85..7051932 100644 --- a/src/GraphClimber/ExpressionImplementation/PropertyStateMemberProvider.cs +++ b/src/GraphClimber/ExpressionImplementation/PropertyStateMemberProvider.cs @@ -5,7 +5,7 @@ namespace GraphClimber { - internal class PropertyStateMemberProvider : IStateMemberProvider + public class PropertyStateMemberProvider : IStateMemberProvider { public IEnumerable Provide(Type type) { diff --git a/src/GraphClimber/ExpressionImplementation/RouteDelegateFactory.cs b/src/GraphClimber/ExpressionImplementation/RouteDelegateFactory.cs index 4965c57..4ca9bc2 100644 --- a/src/GraphClimber/ExpressionImplementation/RouteDelegateFactory.cs +++ b/src/GraphClimber/ExpressionImplementation/RouteDelegateFactory.cs @@ -1,26 +1,22 @@ using System; using System.Linq.Expressions; using System.Reflection; -using GraphClimber.ExpressionCompiler; -using GraphClimber.ExpressionCompiler.Extensions; namespace GraphClimber { internal class RouteDelegateFactory { private readonly IClimbStore _climbStore; - private readonly IExpressionCompiler _compiler; private readonly Type _processorType; private readonly SpecialMethodMutator _specialMutator; private readonly IMethodMapper _methodMapper; - public RouteDelegateFactory(Type processorType, IMethodMapper methodMapper, IClimbStore climbStore, IExpressionCompiler compiler) + public RouteDelegateFactory(Type processorType, IMethodMapper methodMapper, IClimbStore climbStore) { _processorType = processorType; _climbStore = climbStore; _specialMutator = new SpecialMethodMutator(processorType); _methodMapper = methodMapper; - _compiler = compiler; } public RouteDelegate GetRouteDelegate(IStateMember member, Type runtimeMemberType) @@ -58,7 +54,7 @@ public RouteDelegate GetRouteDelegate(IStateMember member, Type runtimeMemberTyp "Route_" + runtimeMemberType.Name, new[] {processor, owner, skipSpecialMethods}); - return _compiler.Compile(lambda); + return lambda.Compile(); } } } \ No newline at end of file diff --git a/src/GraphClimber/ExpressionImplementation/ValueDescriptor.cs b/src/GraphClimber/ExpressionImplementation/ValueDescriptor.cs index 13c9f80..e3f22d5 100644 --- a/src/GraphClimber/ExpressionImplementation/ValueDescriptor.cs +++ b/src/GraphClimber/ExpressionImplementation/ValueDescriptor.cs @@ -77,11 +77,11 @@ protected void Climb(TField value) } else { - ClimReference(value, type); + ClimbReference(value, type); } } - private void ClimReference(TField value, Type type) + private void ClimbReference(TField value, Type type) { if (type == typeof(TRuntime)) { diff --git a/src/GraphClimber/GraphClimber.csproj b/src/GraphClimber/GraphClimber.csproj index 7b7c688..dbdcea4 100644 --- a/src/GraphClimber/GraphClimber.csproj +++ b/src/GraphClimber/GraphClimber.csproj @@ -1,185 +1,7 @@ - - - + + - Debug - AnyCPU - {F7FA4635-C6C6-4D82-B344-B737438E1651} - Exe - Properties - GraphClimber - GraphClimber - v4.5 - 512 - 12.0.0 - 2.0 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true + netstandard2.0 - - AnyCPU - true - full - false - ..\..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - ..\..\bin\Release\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - Microsoft .NET Framework 4.5 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - - - \ No newline at end of file + + diff --git a/src/GraphClimber/Program.cs b/src/GraphClimber/Program.cs deleted file mode 100644 index 5c2e3d4..0000000 --- a/src/GraphClimber/Program.cs +++ /dev/null @@ -1,385 +0,0 @@ -using System; -using System.IO; -using System.Linq.Expressions; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Xml.Linq; -using GraphClimber.Examples; -using GraphClimber.Examples.Binary; -using GraphClimber.ExpressionCompiler; -using GraphClimber.ExpressionCompiler.Extensions; - -namespace GraphClimber -{ - internal class EnumConvert - { - public static readonly Func ToUnderlying = GetToUnderlying(); - public static readonly Func ToEnum = GetToEnum(); - - private static Func GetToUnderlying() - { - return GetConvert(); - } - - private static Func GetToEnum() - { - return GetConvert(); - } - - - private static Func GetConvert() - { - var parameter = Expression.Parameter(typeof(TSource), "value"); - - Expression> lambda = - Expression.Lambda> - (Expression.Convert(parameter, typeof (TTarget)), - parameter); - - return lambda.Compile(); - } - - } - - enum Days - { - Sunday, - Monday, - Tuesday, - Wendensday, - Thursday, - Friday, - Saturday - } - - public class ExpressionDebugGames - { - private static int PrivateField = 2; - - private static int PrivateProperty - { - get { return 5; } - } - - private static int PrivateMethod() - { - return 3; - } - - private static int GenericMethod(TEnum value) where TEnum : IConvertible - { - return 2; - } - - public static void Play() - { - - Expression> hi = () => typeof(int); - - MemberExpression propertyOrField = Expression.Field(null, typeof(ExpressionDebugGames).GetField("PrivateField", BindingFlags.Static | BindingFlags.NonPublic)); - MemberExpression property = Expression.Property(null, typeof(ExpressionDebugGames), "PrivateProperty"); - MethodCallExpression method = Expression.Call(null, - typeof(ExpressionDebugGames).GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(typeof(object))); - - var parameter = Expression.Parameter(typeof(int), "someNumberArgument"); - - var variable = Expression.Variable(typeof(int), "myInt"); - var @break = Expression.Label(); - Expression exp = Expression.Assign(variable, Expression.Divide(propertyOrField, Expression.Subtract(property, method))); - exp = Expression.Block(new[] { variable }, exp, Expression.Add(2.Constant(), 5.Constant()), Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expression.Constant("Hello Worlda"))); - - - var iVariable = Expression.Variable(typeof(int), "i"); - // exp = CustomExpression.For(iVariable, 0.Constant(), Expression.LessThan(iVariable, 5.Constant()), Expression.PostIncrementAssign(iVariable), exp); - - exp = Expression.Block(exp, - Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), - Expression.Constant("Goodbye"))); - - var lambda = Expression.Lambda>(exp, "Hello_World", - new[] { parameter }); - - var expression = new DebugExpressionCompiler(DebugViewExpressionDescriber.Empty).Compile(lambda); - - expression(56); - } - - } - - class SimpleType - { - - - public ValueType SomeValueType { get; set; } - - public string String { get; set; } - - public IConvertible Convertible { get; set; } - - - } - - public class Program - { - private static readonly IStateMemberProvider _stateMemberProvider = new CachingStateMemberProvider(new ReflectionPropertyStateMemberProvider()); - - public static void DoSomething(StrongBox hello) - { - Console.WriteLine(hello); - } - - - static void Main(string[] args) - { - //ExpressionDebugGames.Play(); - //IStore store = new TrivialStore(); - - //store.Set("A", 5); - //store.GetInner("A").Set("A", 10); - - //SerializeDeserializeXML(); - - //SerializeDeserializeStore(); - - SerializeDeserializeBinary(); - } - - public static object GetSimpleTypeInstance() - { - return new SimpleType() - { - Convertible = "sadasd", - SomeValueType = Days.Monday, - String = "Hello W0rld" - }; - } - - public class PersonHolder - { - public IPerson A { get; set; } - public IPerson B { get; set; } - - public IPerson C { get; set; } - } - - private static void SerializeDeserializeBinary() - { - object person = GetSimpleTypeInstance(); - - IPerson structure = new Person2() { Age = 25, Surprise = Days.Monday }; - person = new PersonHolder() { A = structure, B = structure, C = structure }; - - structure.IncreaseAge(); - - //var stateMemberProvider = new BinaryStateMemberProvider(_stateMemberProvider); - var stateMemberProvider = new BinaryStateMemberProvider(new PropertyStateMemberProvider()); - - //var writeClimber = new SlowGraphClimber(stateMemberProvider); - //var readClimber = new SlowGraphClimber(stateMemberProvider); - - var stream = new MemoryStream(); - var binaryWriterProcessor = new BinaryWriterProcessor(new LoggingWriter(new CompressingWriter(new BinaryWriterAdapter(new BinaryWriter(stream))), Console.Out)); - - var writerGraphClimber = DefaultGraphClimber.Create(stateMemberProvider); - - //ClimbDelegate> climb2 = - // store2.GetClimb>(typeof(StrongBox)); - - //climb2(binaryWriterProcessor, - // new StrongBox(person)); - - writerGraphClimber.Climb(new StrongBox(person), binaryWriterProcessor); - - //writeClimber.Route(person, binaryWriterProcessor, false); - - stream.Position = 0; - var binaryReaderProcessor = new BinaryReaderProcessor(new LoggingReader(new DecompressingReader(new BinaryReaderAdapter(new BinaryReader(stream))), Console.Out)); - - var readerGraphClimber = DefaultGraphClimber.Create(stateMemberProvider); - var strongBox = new StrongBox(); - - readerGraphClimber.Climb(strongBox, binaryReaderProcessor); - - - //ClimbStore store = new ClimbStore(binaryReaderProcessor.GetType(), - // new BinaryStateMemberProvider(new PropertyStateMemberProvider()), - // new MethodMapper(), - // new TrivialExpressionCompiler()); - - //ClimbDelegate> climb = store.GetClimb>(typeof (StrongBox)); - - //climb(binaryReaderProcessor, strongBox); - } - - private static void SerializeDeserializeXML() - { - var text = - @" - Shani Elharrar - 24 - - null - 23 - 4 - -"; - - - // Reader code: - SlowGraphClimber climber2 = - new SlowGraphClimber - (_stateMemberProvider); - - XElement reader = XElement.Parse(text); - - XmlReaderProcessor processor2 = - new XmlReaderProcessor(reader); - - Person person2 = new Person(); - - climber2.Climb(person2, - processor2); - - - // Writer code: - SlowGraphClimber climber = - new SlowGraphClimber - (_stateMemberProvider); - - Person person = new Person() - { - Age = 24, - Name = "Shani Elharrar", - Surprise = new Person() - { - Age = 23, - Name = null, - Surprise = 4 - } - }; - - XmlWriterProcessor processor = new XmlWriterProcessor(); - - climber.Climb(person, - processor); - } - - public struct MyClass - { - public string Name { get; set; } - } - - class Person - { - public Person() - { - //Children = new List(); - } - - public string Name { get; set; } - - public int Age { get; set; } - - public object Surprise { get; set; } - - public Person Father { get; set; } - - //public IList Children { get; set; } - } - - internal struct Person2 : IPerson - { - public string Name { get; set; } - - public int Age { get; set; } - - public object Surprise { get; set; } - - public object Father { get; set; } - - public Days Day { get; set; } - public void IncreaseAge() - { - Age++; - } - } - - - public static void SerializeDeserializeStore() - { - var store = new TrivialStore(); - - SlowGraphClimber climber = new SlowGraphClimber(_stateMemberProvider); - - var processor = new StoreWriterProcessor(store); - var box = new StrongBox(GetPerson()); - - climber.Climb(box, processor); - - - SlowGraphClimber readerClimber = new SlowGraphClimber(_stateMemberProvider); - - var readerProcessor = new StoreReaderProcessor(store); - var readBox = new StrongBox(null); - readerClimber.Climb(readBox, readerProcessor); - - } - - private static Person GetPerson() - { - var ilan = new Person { Age = 26 + 25, Name = "Ilan Zelingher", Surprise = 1 }; - ilan.Surprise = ilan; - return new Person() - { - Age = 26, - Name = "Elad Zelinger", - Father = ilan, - //Children = { new Person() { Name = "Jason"}, new Person() { Name = "Tomerh" }}, - Surprise = new Person() - { - Age = 21, - Name = "Yosi Attias", - Surprise = new MyClass() - { - Name = "YO!" - } - } - }; - } - - private static Person2 GetPerson2() - { - Person2 ilan = new Person2 { Age = 26 + 25, Name = "Ilan Zelingher" }; - - ilan.Surprise = ilan; - return new Person2() - { - Age = 26, - Name = "Elad Zelinger", - Father = ilan, - Day = Days.Tuesday, - Surprise = new Person2() - { - Age = 21, - Name = "Yosi Attias", - Surprise =ilan - //new object[] - //{ - // ilan, ilan, 342, "Hello", - // new int[,]{{1,1},{2,3},{5,8}}, - // new int[]{1,1,2,3,5,8}, - // Days.Saturday - //} - } - }; - - } - } - - public interface IPerson - { - - void IncreaseAge(); - - } -} \ No newline at end of file diff --git a/src/GraphClimber/Properties/AssemblyInfo.cs b/src/GraphClimber/Properties/AssemblyInfo.cs deleted file mode 100644 index 56a3be0..0000000 --- a/src/GraphClimber/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("GraphClimber")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("CodeSharp")] -[assembly: AssemblyProduct("GraphClimber")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: InternalsVisibleTo("GraphClimber.Debug")] -[assembly: InternalsVisibleTo("GraphClimber.RuntimeGenerated")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f7fa4635-c6c6-4d82-b344-b737438e1651")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/GraphClimber/SlowGraphClimber.cs b/src/GraphClimber/SlowGraphClimber.cs deleted file mode 100644 index ddfff39..0000000 --- a/src/GraphClimber/SlowGraphClimber.cs +++ /dev/null @@ -1,797 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using GraphClimber.ValueDescriptor; - -namespace GraphClimber -{ - public class CachingStateMemberProvider : IStateMemberProvider - { - private readonly IStateMemberProvider _underlying; - - private readonly IDictionary> _cache = new Dictionary>(); - private readonly object _syncRoot = new object(); - - public CachingStateMemberProvider(IStateMemberProvider underlying) - { - _underlying = underlying; - } - - public IEnumerable Provide(Type type) - { - IEnumerable retVal; - if (_cache.TryGetValue(type, out retVal)) - { - return retVal; - } - - lock (_syncRoot) - { - if (!_cache.TryGetValue(type, out retVal)) - { - // ToList() is here to cache yield return methods. - _cache[type] = retVal = _underlying.Provide(type).ToList(); - } - } - - return retVal; - } - - public IStateMember ProvideArrayMember(Type arrayType, int[] indices) - { - // TODO : May not be smart performance wise. - return new ArrayStateMember(arrayType, arrayType.GetElementType(), indices); - } - } - - internal class ReflectionPropertyStateMemberProvider : IStateMemberProvider - { - public IEnumerable Provide(Type type) - { - return type.GetRuntimeProperties() - .Where(x => x.GetIndexParameters().Length == 0) - .Select(x => new ReflectionPropertyStateMember(x)); - } - - public IStateMember ProvideArrayMember(Type arrayType, int[] indices) - { - return new ArrayStateMember(arrayType, arrayType.GetElementType(), indices); - } - } - - - - internal class ReflectionPropertyStateMember : IReflectionStateMember - { - private readonly PropertyInfo _property; - - public ReflectionPropertyStateMember(PropertyInfo property) - { - _property = property; - } - - public string Name - { - get { return _property.Name; } - } - - public Type OwnerType - { - get { return _property.ReflectedType; } - } - - public virtual Type MemberType - { - get { return _property.PropertyType; } - } - - public bool CanRead - { - get { return _property.CanRead; } - } - - public bool CanWrite - { - get { return _property.CanWrite; } - } - - public Expression GetGetExpression(Expression obj) - { - throw new NotImplementedException(); - } - - public Expression GetSetExpression(Expression obj, Expression value) - { - throw new NotImplementedException(); - } - - public bool IsArrayElement - { - get { return false; } - } - - public int[] ElementIndex - { - get - { - // The empty index - return new int[0]; - } - } - - public MemberInfo UnderlyingMemberInfo - { - get - { - return _property; - } - } - - public object GetValue(object owner) - { - return _property.GetValue(owner); - } - - public void SetValue(object owner, object value) - { - _property.SetValue(owner, value); - } - } - - public interface IReflectionStateMember : IStateMember - { - MemberInfo UnderlyingMemberInfo { get; } - - object GetValue(object owner); - - void SetValue(object owner, object value); - } - - internal class ReflectionValueDescriptor : - IReadOnlyValueDescriptor, - IReadOnlyExactValueDescriptor, - IWriteOnlyExactValueDescriptor, - IWriteOnlyValueDescriptor, - IReadWriteValueDescriptor, - IReflectionValueDescriptor where - TRuntime : TField - { - private readonly IStateMemberProvider _stateMemberProvider; - private readonly IReflectionStateMember _stateMember; - private readonly object _owner; - private readonly object _processor; - - public ReflectionValueDescriptor(object processor, IStateMemberProvider stateMemberProvider, - IReflectionStateMember stateMember, object owner) - { - _stateMemberProvider = stateMemberProvider; - _stateMember = stateMember; - _owner = owner; - _processor = processor; - } - - public TField Get() - { - return (TField) _stateMember.GetValue(_owner); - } - - object IReflectionValueDescriptor.Get() - { - return Get(); - } - - TRuntime IReadOnlyValueDescriptor.Get() - { - return (TRuntime) Get(); - } - - TRuntime IReadOnlyExactValueDescriptor.Get() - { - IReadOnlyValueDescriptor casted = this; - return casted.Get(); - } - - public void Set(TField value) - { - _stateMember.SetValue(_owner, value); - } - - public IStateMember StateMember - { - get { return _stateMember; } - } - - public object Owner - { - get { return _owner; } - } - - public void Climb() - { - TField value = Get(); - - Type runtimeType; - - if (value != null) - { - runtimeType = value.GetType(); - } - else - { - throw new NullReferenceException("Can't climb on null, you silly developer!"); - } - - if (runtimeType.IsArray) - { - ClimbArray((Array) (object) value); - } - else - { - IEnumerable members = - _stateMemberProvider.Provide(runtimeType); - - object boxed = value; - - foreach (IReflectionStateMember member in - members.Cast()) - { - Type runtimeMemberType = GetRuntimeMemberType(member, value); - VisitMember(member, boxed, runtimeMemberType, false, false); - } - - if (runtimeType.IsValueType) - { - Set((TField) boxed); - } - } - } - - private void ClimbArray(Array array) - { - int dimension = array.Rank; - - IEnumerable> indexesSets = - Enumerable.Range(0, dimension) - .Select(index => Enumerable.Range(array.GetLowerBound(index), - array.GetLength(index))); - - IEnumerable> allIndexes = - Combinatorics.CartesianProduct(indexesSets.Reverse()); - - foreach (IEnumerable indexSet in allIndexes) - { - int[] indices = indexSet.Reverse().ToArray(); - - IReflectionStateMember decorated = (IReflectionStateMember) - _stateMemberProvider.ProvideArrayMember(array.GetType(), indices); - - Type runtimeMemberType = GetRuntimeMemberType(decorated, array); - - VisitMember(decorated, array, runtimeMemberType, false, false); - } - } - - private Type GetRuntimeMemberType(IReflectionStateMember member, object value) - { - Type memberType = member.MemberType; - - object memberValue = member.GetValue(value); - - var result = - memberValue != null ? memberValue.GetType() : memberType; - - return result; - } - - private void VisitMember(IReflectionStateMember member, - object owner, - Type runtimeMemberType, - bool skipSpecialMethod, - bool routed) - { - IReflectionValueDescriptor descriptor = - CreateDescriptor(member, owner, runtimeMemberType); - - CallProcess(descriptor, skipSpecialMethod, routed); - } - - private IReflectionValueDescriptor CreateDescriptor(IReflectionStateMember member, object value, - Type runtimeMemberType) - { - Type descriptorType; - - Type memberType = member.MemberType; - if (memberType.IsEnum) - { - descriptorType = typeof (ReflectionEnumValueDescriptor<,,>) - .MakeGenericType(memberType, runtimeMemberType, - memberType.GetEnumUnderlyingType()); - } - else - { - descriptorType = typeof(ReflectionValueDescriptor<,>) - .MakeGenericType(memberType, runtimeMemberType); - } - - IReflectionValueDescriptor descriptor = - (IReflectionValueDescriptor) Activator.CreateInstance - (descriptorType, - _processor, _stateMemberProvider, member, value); - - return descriptor; - } - - public void Route(IStateMember stateMember, object owner, bool skipSpecialMethod = true) - { - VisitMember((IReflectionStateMember) stateMember, - owner, - stateMember.MemberType, - skipSpecialMethod, true); - } - - public void Route(IStateMember stateMember, Type runtimeMemberType, object owner, bool skipSpecialMethod = true) - { - VisitMember((IReflectionStateMember) stateMember, - owner, - runtimeMemberType, - skipSpecialMethod, true); - } - - private void CallProcess(IReflectionValueDescriptor descriptor, bool skipSpecialMethod, bool routed) - { - Type fieldType = descriptor.StateMember.MemberType; - - bool methodCalled = false; - - if (!fieldType.IsValueType && !skipSpecialMethod) - { - methodCalled = TryCallSpecialMethod(descriptor, fieldType); - } - - if (!methodCalled) - { - CallMatchedProcess(descriptor, routed); - } - } - - private bool TryCallSpecialMethod(IReflectionValueDescriptor descriptor, Type fieldType) - { - object value = descriptor.Get(); - - INullProcessor processor = _processor as INullProcessor; - IRevisitedProcessor revisitedProcessor = _processor as IRevisitedProcessor; - - if (processor != null && value == null) - { - CallGenericMethod(descriptor, typeof (INullProcessor), fieldType, "ProcessNull"); - return true; - } - else if ((value != null) && - (revisitedProcessor != null) && - revisitedProcessor.Visited(value)) - { - CallGenericMethod(descriptor, typeof (IRevisitedProcessor), fieldType, "ProcessRevisited"); - return true; - } - - return false; - } - - private void CallGenericMethod(IReflectionValueDescriptor descriptor, Type processorType, Type genericType, string methodName) - { - MethodInfo methodToCall = - processorType.GetMethod(methodName) - .MakeGenericMethod(genericType); - - methodToCall.Invoke(_processor, new object[] {descriptor}); - } - - private void CallMatchedProcess(IReflectionValueDescriptor descriptor, bool routed) - { - GenericArgumentBinder binder = new GenericArgumentBinder(new FallbackToFirstCandidateMethodSelector(new BinderMethodSelector(Type.DefaultBinder))); - - IEnumerable methods = - _processor.GetType().GetMethods() - .Where(x => x.IsDefined(typeof (ProcessorMethodAttribute))) - .Where(x => !x.GetCustomAttribute().OnlyOnRoute || routed); - - Type descriptorType = descriptor.GetType(); - - IEnumerable> candidates = - methods.Select(method => Bind(binder, method, descriptorType)) - .Where(x => x != null) - .GroupBy(x => x.GetCustomAttribute().Precedence) - .OrderBy(x => x.Key); - - IGrouping maximum = candidates.FirstOrDefault(); - - if (maximum.Skip(1).Any()) - { - throw new Exception("Too many candidates for the processor thingy. Use precedence."); - } - else - { - MethodInfo method = maximum.FirstOrDefault(); - - if (method != null) - { - method.Invoke(_processor, new object[] {descriptor}); - } - else - { - throw new Exception( - "No method found :(, this might be a bug in your code, or in the GraphClimber. Good luck."); - } - } - } - - private MethodInfo Bind(GenericArgumentBinder binder, MethodInfo method, Type descriptorType) - { - MethodInfo bindedMethod; - - if (binder.TryBind(method, new[] {descriptorType}, out bindedMethod)) - { - return bindedMethod; - } - - return null; - } - } - - internal class ReflectionEnumValueDescriptor : - ReflectionValueDescriptor, - IReadOnlyEnumExactValueDescriptor, - IWriteOnlyEnumExactValueDescriptor - where TRuntime : TField - where TField : IConvertible - where TUnderlying : IConvertible - { - private readonly IStateMember _underlyingValueStateMember; - - public ReflectionEnumValueDescriptor(object processor, IStateMemberProvider stateMemberProvider, IReflectionStateMember stateMember, object owner) : - base(processor, stateMemberProvider, stateMember, owner) - { - _underlyingValueStateMember = new EnumUnderlyingValueStateMember(stateMember); - } - - public TUnderlying GetUnderlying() - { - TField result = Get(); - - TUnderlying value = - (TUnderlying) Convert.ChangeType(result, typeof (TUnderlying)); - - return value; - } - - public void SetUnderlying(TUnderlying value) - { - long asLong = - (long) Convert.ChangeType(value, typeof (long)); - - TField result = - (TField) Enum.ToObject(typeof (TField), asLong); - - Set(result); - } - - public IStateMember UnderlyingValueStateMember - { - get - { - return _underlyingValueStateMember; - } - } - } - - internal class EnumUnderlyingValueStateMember : IReflectionStateMember - { - private readonly IReflectionStateMember _stateMember; - private readonly Type _enumType; - private readonly Type _underlyingType; - - public EnumUnderlyingValueStateMember(IReflectionStateMember stateMember) - { - _stateMember = stateMember; - _enumType = _stateMember.MemberType; - _underlyingType = _enumType.GetEnumUnderlyingType(); - } - - public string Name - { - get { return _stateMember.Name; } - } - - public Type OwnerType - { - get { return _stateMember.OwnerType; } - } - - public Type MemberType - { - get { return _underlyingType; } - } - - public bool CanRead - { - get { return _stateMember.CanRead; } - } - - public bool CanWrite - { - get { return _stateMember.CanWrite; } - } - - public Expression GetGetExpression(Expression obj) - { - return _stateMember.GetGetExpression(obj); - } - - public Expression GetSetExpression(Expression obj, Expression value) - { - return _stateMember.GetSetExpression(obj, value); - } - - public bool IsArrayElement - { - get { return _stateMember.IsArrayElement; } - } - - public int[] ElementIndex - { - get { return _stateMember.ElementIndex; } - } - - public MemberInfo UnderlyingMemberInfo - { - get { return _stateMember.UnderlyingMemberInfo; } - } - - public object GetValue(object owner) - { - return Convert.ChangeType(_stateMember.GetValue(owner), _underlyingType); - } - - public void SetValue(object owner, object value) - { - // Thats how they do it :( - object casted = - Enum.ToObject(_enumType, Convert.ToInt64(value)); - - _stateMember.SetValue(owner, casted); - } - } - - internal class ArrayStateMember : IReflectionStateMember - { - private readonly Type _arrayType; - private readonly Type _arrayElementType; - private readonly int[] _indices; - - public ArrayStateMember(Type arrayType, Type arrayElementType, int[] indices) - { - _arrayType = arrayType; - _arrayElementType = arrayElementType; - _indices = indices; - } - - public string Name - { - get - { - return string.Format("[{0}]", - string.Join(", ", _indices)); - } - } - - public Type OwnerType - { - get - { - return _arrayType; - } - } - - public Type MemberType - { - get - { - return _arrayElementType; - } - } - - public bool CanRead - { - get { return true; } - } - - public bool CanWrite - { - get { return true; } - } - - public Expression GetGetExpression(Expression obj) - { - throw new NotImplementedException(); - } - - public Expression GetSetExpression(Expression obj, Expression value) - { - throw new NotImplementedException(); - } - - public bool IsArrayElement - { - get - { - return true; - } - } - - public int[] ElementIndex - { - get - { - return _indices; - } - } - - public MemberInfo UnderlyingMemberInfo - { - get { throw new NotImplementedException(); } - } - - public object GetValue(object owner) - { - Array array = owner as Array; - return array.GetValue(_indices); - } - - public void SetValue(object owner, object value) - { - Array array = owner as Array; - array.SetValue(value, _indices); - } - } - - internal interface IReflectionValueDescriptor : IValueDescriptor - { - object Get(); - } - - - public class SlowGraphClimber : IGraphClimber - { - private readonly IStateMemberProvider _stateMemberProvider; - - public SlowGraphClimber(IStateMemberProvider stateMemberProvider) - { - _stateMemberProvider = stateMemberProvider; - } - - public void Climb(object parent, TProcessor processor) - { - var descriptor = GetDescriptor(parent, processor); - - descriptor.Climb(); - } - - public void Route(IStateMember stateMember, object current, TProcessor processor, bool skipSpecialMethod) - { - throw new NotImplementedException(); - } - - public void Route(object current, TProcessor processor, bool skipSpecialMethod) - { - var descriptor = GetDescriptor(current, processor); - - descriptor.Route(descriptor.StateMember, current.GetType(), new Box { Parent = current }, skipSpecialMethod); - } - - - private ReflectionValueDescriptor GetDescriptor(object current, TProcessor processor) - { - var descriptor = - new ReflectionValueDescriptor(processor, - _stateMemberProvider, - new StaticStateMember(current), - null); - return descriptor; - } - - - private class Box - { - public object Parent { get; set; } - } - } - - /* - public class StaticValueDescriptor : IReadOnlyValueDescriptor, - IReadOnlyExactValueDescriptor, - IReadWriteValueDescriptor - { - private readonly object _current; - private readonly object _processor; - - public StaticValueDescriptor(object current, object processor) - { - _current = current; - _processor = processor; - throw new NotImplementedException(); - } - - public void Set(object value) - { - throw new NotImplementedException(); - } - - public object Get() - { - return _current; - } - - public IStateMember StateMember - { - get { return StaticStateMember.Empty; } - } - - public class StaticStateMember : IStateMember - { - public static readonly IStateMember Empty = new StaticStateMember(); - - private StaticStateMember() - { - - } - - - public string Name - { - get { return "InitialValue"; } - } - - public Type OwnerType - { - get { return typeof (object); } - } - - public Type MemberType - { - get { return typeof(object); } - } - - public Expression GetGetExpression(Expression obj) - { - throw new NotImplementedException(); - } - - public Expression GetSetExpression(Expression obj, Expression value) - { - throw new NotImplementedException(); - } - } - - public object Owner - { - get { throw new NotImplementedException(); } - } - - public void Climb() - { - throw new NotImplementedException(); - } - - public void Route(IStateMember stateMember, Type runtimeMemberType, object owner) - { - throw new NotImplementedException(); - } - - public void Route(IStateMember stateMember, object owner) - { - throw new NotImplementedException(); - } - }*/ -} \ No newline at end of file diff --git a/src/GraphClimber/ValueDescriptor/DelegateStateMember.cs b/src/GraphClimber/ValueDescriptor/DelegateStateMember.cs index 74f882d..1e1cde4 100644 --- a/src/GraphClimber/ValueDescriptor/DelegateStateMember.cs +++ b/src/GraphClimber/ValueDescriptor/DelegateStateMember.cs @@ -2,11 +2,10 @@ using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; -using GraphClimber.ExpressionCompiler.Extensions; namespace GraphClimber.ValueDescriptor { - public class StaticStateMember : IReflectionStateMember + public class StaticStateMember : IStateMember { private readonly object _value; private readonly string _name; @@ -61,24 +60,9 @@ public int[] ElementIndex { get { throw new NotImplementedException(); } } - - public MemberInfo UnderlyingMemberInfo - { - get { throw new NotImplementedException(); } - } - - public object GetValue(object owner) - { - return _value; - } - - public void SetValue(object owner, object value) - { - // Does nothing! - } } - public class StrongBoxStateMember : IReflectionStateMember + public class StrongBoxStateMember : IStateMember { private readonly StrongBox _strongBox; private readonly string _name; @@ -149,161 +133,4 @@ public void SetValue(object owner, object value) _strongBox.Value = (T) value; } } - - public class DelegateStateMember : IReflectionStateMember - { - private readonly Type _memberType; - private readonly Func _getValue; - private readonly Action _setValue; - - public DelegateStateMember(Type memberType, Func getValue, Action setValue) - { - _memberType = memberType; - _getValue = getValue; - _setValue = setValue; - } - - - public string Name - { - get { return "Value"; } - } - - public Type OwnerType - { - get { throw new NotSupportedException(); } - } - - public Type MemberType - { - get { return _memberType; } - } - - public bool CanRead - { - get { return true; } - } - - public bool CanWrite - { - get { return true; } - } - - public Expression GetGetExpression(Expression obj) - { - return Expression.Invoke(_getValue.Constant()); - } - - public Expression GetSetExpression(Expression obj, Expression value) - { - return Expression.Invoke(_setValue.Constant(), value); - } - - public bool IsArrayElement - { - get { return false; } - } - - public int[] ElementIndex - { - get { throw new NotSupportedException(); } - } - - public MemberInfo UnderlyingMemberInfo - { - get { throw new NotImplementedException(); } - } - - public object GetValue(object owner) - { - return _getValue(); - } - - public void SetValue(object owner, object value) - { - _setValue(value); - } - - public static IReflectionStateMember Create(Type memberType, Func getValue, Action setValue) - { - return new DelegateStateMember(memberType, getValue, setValue); - } - - public static IReflectionStateMember Create(Func getValue, Action setValue) - { - return new SafeDelegateStateMember(getValue, setValue); - } - } - - public class SafeDelegateStateMember : IReflectionStateMember - { - private readonly Func _getValue; - private readonly Action _setValue; - - public SafeDelegateStateMember(Func getValue, Action setValue) - { - _getValue = getValue; - _setValue = setValue; - } - - public string Name - { - get { return "Value"; } - } - - public Type OwnerType - { - get { throw new NotSupportedException(); } - } - - public Type MemberType - { - get { return typeof (T); } - } - - public bool CanRead - { - get { return true; } - } - - public bool CanWrite - { - get { return true; } - } - - public Expression GetGetExpression(Expression obj) - { - return Expression.Invoke(_getValue.Constant()); - } - - public Expression GetSetExpression(Expression obj, Expression value) - { - return Expression.Invoke(_setValue.Constant(), value); - } - - public bool IsArrayElement - { - get { return false; } - } - - public int[] ElementIndex - { - get { throw new NotSupportedException(); } - } - - public MemberInfo UnderlyingMemberInfo - { - get { throw new NotImplementedException(); } - } - - public object GetValue(object owner) - { - return _getValue(); - } - - public void SetValue(object owner, object value) - { - _setValue((T) value); - } - } } diff --git a/src/GraphClimber/ValueDescriptor/IEnumValueDescriptor.cs b/src/GraphClimber/ValueDescriptor/IEnumValueDescriptor.cs index 7f2f6e1..b04b033 100644 --- a/src/GraphClimber/ValueDescriptor/IEnumValueDescriptor.cs +++ b/src/GraphClimber/ValueDescriptor/IEnumValueDescriptor.cs @@ -14,7 +14,7 @@ public interface IEnumValueDescriptor public interface IReadOnlyEnumExactValueDescriptor : IEnumValueDescriptor, IReadOnlyExactValueDescriptor - where TEnum : IConvertible + where TEnum : Enum where TUnderlying : IConvertible { /// @@ -31,7 +31,7 @@ public interface IReadOnlyEnumExactValueDescriptor : public interface IWriteOnlyEnumExactValueDescriptor : IEnumValueDescriptor, IWriteOnlyExactValueDescriptor - where TEnum : IConvertible + where TEnum : Enum where TUnderlying : IConvertible { ///