| 1 |
using System; |
|---|
| 2 |
using System.Collections.Generic; |
|---|
| 3 |
using System.Linq; |
|---|
| 4 |
using System.Text; |
|---|
| 5 |
using System.Linq.Expressions; |
|---|
| 6 |
using System.Xml; |
|---|
| 7 |
using System.Collections; |
|---|
| 8 |
using System.Reflection; |
|---|
| 9 |
|
|---|
| 10 |
namespace IfIHadABoat.Part5 |
|---|
| 11 |
{ |
|---|
| 12 |
interface ILocation |
|---|
| 13 |
{ |
|---|
| 14 |
string Name { get; set; } |
|---|
| 15 |
} |
|---|
| 16 |
|
|---|
| 17 |
interface IPony : ILocation |
|---|
| 18 |
{ |
|---|
| 19 |
IPony Ride(ILocation location); |
|---|
| 20 |
} |
|---|
| 21 |
|
|---|
| 22 |
interface IBoat : ILocation |
|---|
| 23 |
{ |
|---|
| 24 |
IBoat GoOut(ILocation location); |
|---|
| 25 |
} |
|---|
| 26 |
|
|---|
| 27 |
class Program |
|---|
| 28 |
{ |
|---|
| 29 |
static public void Example() |
|---|
| 30 |
{ |
|---|
| 31 |
Expression<Action<IBoat, IPony, ILocation>> e3 = |
|---|
| 32 |
(boat, pony, place) => pony.Ride(boat == null ? place : boat.GoOut(place)); |
|---|
| 33 |
|
|---|
| 34 |
Action<IBoat, IPony, ILocation> x3 = e3.Compile(); |
|---|
| 35 |
|
|---|
| 36 |
var myPony = new Pony { Name = "my pony" }; |
|---|
| 37 |
var myBoat = new Boat { Name = "my boat" }; |
|---|
| 38 |
var theOcean = new Location { Name = "the ocean" }; |
|---|
| 39 |
|
|---|
| 40 |
x3(myBoat, myPony, theOcean); |
|---|
| 41 |
// my boat go out on the ocean |
|---|
| 42 |
// my pony ride on my boat |
|---|
| 43 |
|
|---|
| 44 |
x3(null, new Pony(), new Location { Name = "through the desert" }); |
|---|
| 45 |
// no name ride on through the desert |
|---|
| 46 |
|
|---|
| 47 |
ShowIt(e3); |
|---|
| 48 |
// big chunks of xml |
|---|
| 49 |
} |
|---|
| 50 |
|
|---|
| 51 |
static void ShowIt(Expression e) |
|---|
| 52 |
{ |
|---|
| 53 |
XmlDocument doc = new XmlDocument(); |
|---|
| 54 |
doc.AppendChild(doc.CreateElement("e")); |
|---|
| 55 |
Make(doc.DocumentElement, e, new Stack<object>()); |
|---|
| 56 |
using (XmlTextWriter writer = new XmlTextWriter(Console.Out)) |
|---|
| 57 |
{ |
|---|
| 58 |
writer.Formatting = Formatting.Indented; |
|---|
| 59 |
writer.Indentation = 2; |
|---|
| 60 |
writer.IndentChar = ' '; |
|---|
| 61 |
doc.WriteTo(writer); |
|---|
| 62 |
} |
|---|
| 63 |
} |
|---|
| 64 |
|
|---|
| 65 |
static void Make(XmlElement elt, object obj, Stack<object> dontBeCyclical) |
|---|
| 66 |
{ |
|---|
| 67 |
dontBeCyclical.Push(obj); |
|---|
| 68 |
try |
|---|
| 69 |
{ |
|---|
| 70 |
Type type = obj.GetType(); |
|---|
| 71 |
|
|---|
| 72 |
if (obj is Expression) |
|---|
| 73 |
{ |
|---|
| 74 |
elt.ParentNode.InsertBefore(elt.OwnerDocument.CreateComment(obj.ToString()), elt); |
|---|
| 75 |
} |
|---|
| 76 |
|
|---|
| 77 |
|
|---|
| 78 |
foreach (var propInfo in type.GetProperties()) |
|---|
| 79 |
{ |
|---|
| 80 |
object value; |
|---|
| 81 |
try |
|---|
| 82 |
{ |
|---|
| 83 |
value = propInfo.GetValue(obj, null); |
|---|
| 84 |
} |
|---|
| 85 |
catch (Exception ex) |
|---|
| 86 |
{ |
|---|
| 87 |
value = ex.Message; |
|---|
| 88 |
} |
|---|
| 89 |
|
|---|
| 90 |
|
|---|
| 91 |
if (value == null) |
|---|
| 92 |
continue; |
|---|
| 93 |
|
|---|
| 94 |
if (typeof(Type).IsAssignableFrom(type) && propInfo.Name != "Name") |
|---|
| 95 |
continue; |
|---|
| 96 |
if (typeof(MemberInfo).IsAssignableFrom(type) && propInfo.Name != "Name") |
|---|
| 97 |
continue; |
|---|
| 98 |
|
|---|
| 99 |
if (value.GetType().IsPrimitive || value is string || value is Enum) |
|---|
| 100 |
{ |
|---|
| 101 |
elt.Attributes.Append(elt.OwnerDocument.CreateAttribute(propInfo.Name)).Value = Convert.ToString(value); |
|---|
| 102 |
continue; |
|---|
| 103 |
} |
|---|
| 104 |
|
|---|
| 105 |
XmlElement valueElt = elt.OwnerDocument.CreateElement(XmlConvert.EncodeName(value.GetType().Name + "-" + propInfo.Name)); |
|---|
| 106 |
elt.AppendChild(valueElt); |
|---|
| 107 |
if (dontBeCyclical.Contains(value)) |
|---|
| 108 |
{ |
|---|
| 109 |
valueElt.AppendChild(elt.OwnerDocument.CreateTextNode("Cyclical object " + Convert.ToString(value))); |
|---|
| 110 |
} |
|---|
| 111 |
else if (value is IEnumerable) |
|---|
| 112 |
{ |
|---|
| 113 |
elt.RemoveChild(valueElt); |
|---|
| 114 |
valueElt = elt.OwnerDocument.CreateElement(propInfo.Name); |
|---|
| 115 |
elt.AppendChild(valueElt); |
|---|
| 116 |
foreach (var item in value as IEnumerable) |
|---|
| 117 |
{ |
|---|
| 118 |
XmlElement itemElt = elt.OwnerDocument.CreateElement(item.GetType().Name); |
|---|
| 119 |
valueElt.AppendChild(itemElt); |
|---|
| 120 |
Make(itemElt, item, dontBeCyclical); |
|---|
| 121 |
} |
|---|
| 122 |
} |
|---|
| 123 |
else |
|---|
| 124 |
{ |
|---|
| 125 |
Make(valueElt, value, dontBeCyclical); |
|---|
| 126 |
} |
|---|
| 127 |
|
|---|
| 128 |
//elt.Attributes.Append(elt.OwnerDocument.CreateAttribute(propInfo.Name)).Value = Convert.ToString(value); |
|---|
| 129 |
} |
|---|
| 130 |
} |
|---|
| 131 |
finally |
|---|
| 132 |
{ |
|---|
| 133 |
dontBeCyclical.Pop(); |
|---|
| 134 |
} |
|---|
| 135 |
} |
|---|
| 136 |
} |
|---|
| 137 |
|
|---|
| 138 |
class Location : ILocation |
|---|
| 139 |
{ |
|---|
| 140 |
public string Name { get; set; } |
|---|
| 141 |
} |
|---|
| 142 |
|
|---|
| 143 |
|
|---|
| 144 |
class Pony : IPony |
|---|
| 145 |
{ |
|---|
| 146 |
public string Name { get; set; } |
|---|
| 147 |
|
|---|
| 148 |
public IPony Ride(ILocation location) |
|---|
| 149 |
{ |
|---|
| 150 |
Console.WriteLine("{0} ride on {1}", this.Name ?? "no name", location.Name); |
|---|
| 151 |
return this; |
|---|
| 152 |
} |
|---|
| 153 |
} |
|---|
| 154 |
|
|---|
| 155 |
class Boat : IBoat |
|---|
| 156 |
{ |
|---|
| 157 |
public string Name { get; set; } |
|---|
| 158 |
|
|---|
| 159 |
public IBoat GoOut(ILocation location) |
|---|
| 160 |
{ |
|---|
| 161 |
Console.WriteLine("{0} go out on {1}", this.Name ?? "no name", location.Name); |
|---|
| 162 |
return this; |
|---|
| 163 |
} |
|---|
| 164 |
} |
|---|
| 165 |
|
|---|
| 166 |
} |
|---|