1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Text;
|
---|
4 | using System.Reflection;
|
---|
5 |
|
---|
6 | namespace Persistence {
|
---|
7 |
|
---|
8 | [AttributeUsage(
|
---|
9 | AttributeTargets.Field | AttributeTargets.Property,
|
---|
10 | AllowMultiple=false,
|
---|
11 | Inherited=false)]
|
---|
12 | public class StorableAttribute : Attribute {
|
---|
13 |
|
---|
14 | private string name = null;
|
---|
15 | private object defaultValue = null;
|
---|
16 |
|
---|
17 | public string Name {
|
---|
18 | get { return this.name; }
|
---|
19 | set { this.name = value; }
|
---|
20 | }
|
---|
21 |
|
---|
22 | public object DefaultValue {
|
---|
23 | get { return this.defaultValue; }
|
---|
24 | set { this.defaultValue = value; }
|
---|
25 | }
|
---|
26 |
|
---|
27 | private const BindingFlags instanceMembers =
|
---|
28 | BindingFlags.Instance |
|
---|
29 | BindingFlags.Public |
|
---|
30 | BindingFlags.NonPublic;
|
---|
31 |
|
---|
32 | public static Dictionary<string, DataMemberAccessor> GetAutostorableAccessors(object obj) {
|
---|
33 | Dictionary<string, DataMemberAccessor> autoStorableAccessors =
|
---|
34 | new Dictionary<string, DataMemberAccessor>();
|
---|
35 | foreach (MemberInfo memberInfo in obj.GetType().GetMembers(instanceMembers)) {
|
---|
36 | foreach (object attribute in memberInfo.GetCustomAttributes(false)) {
|
---|
37 | StorableAttribute autoStorableAttribute =
|
---|
38 | attribute as StorableAttribute;
|
---|
39 | if (autoStorableAttribute != null) {
|
---|
40 | autoStorableAccessors.Add(memberInfo.Name,
|
---|
41 | new DataMemberAccessor(memberInfo, autoStorableAttribute, obj));
|
---|
42 | }
|
---|
43 | }
|
---|
44 | }
|
---|
45 | return autoStorableAccessors;
|
---|
46 | }
|
---|
47 | }
|
---|
48 |
|
---|
49 | public interface IDataMemberAccessor {
|
---|
50 | string Name { get; }
|
---|
51 | Type Type { get; }
|
---|
52 | object DefaultValue { get; }
|
---|
53 | object Get();
|
---|
54 | void Set(object value);
|
---|
55 | }
|
---|
56 |
|
---|
57 | public class DataMemberAccessor : IDataMemberAccessor {
|
---|
58 |
|
---|
59 | public delegate object Getter();
|
---|
60 | public delegate void Setter(object value);
|
---|
61 |
|
---|
62 | private string name;
|
---|
63 | private Type type;
|
---|
64 | private object defaultValue;
|
---|
65 | private Getter getter;
|
---|
66 | private Setter setter;
|
---|
67 |
|
---|
68 | public DataMemberAccessor(
|
---|
69 | MemberInfo memberInfo,
|
---|
70 | StorableAttribute autoStorableAttribute,
|
---|
71 | object obj) {
|
---|
72 | if (memberInfo.MemberType == MemberTypes.Field) {
|
---|
73 | FieldInfo fieldInfo = (FieldInfo)memberInfo;
|
---|
74 | this.getter = () => fieldInfo.GetValue(obj);
|
---|
75 | this.setter = (value) => fieldInfo.SetValue(obj, value);
|
---|
76 | this.type = fieldInfo.FieldType;
|
---|
77 | } else if (memberInfo.MemberType == MemberTypes.Property) {
|
---|
78 | PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
|
---|
79 | if (!propertyInfo.CanRead || !propertyInfo.CanWrite) {
|
---|
80 | throw new NotSupportedException(
|
---|
81 | "Storable properties must implement both a Get and a Set accessor. ");
|
---|
82 | }
|
---|
83 | this.getter = () => propertyInfo.GetValue(obj, null);
|
---|
84 | this.setter = (value) => propertyInfo.SetValue(obj, value, null);
|
---|
85 | this.type = propertyInfo.PropertyType;
|
---|
86 | } else {
|
---|
87 | throw new NotSupportedException(
|
---|
88 | "The Storable attribute can only be applied to fields and properties.");
|
---|
89 | }
|
---|
90 | this.name = autoStorableAttribute.Name != null ? autoStorableAttribute.Name : memberInfo.Name;
|
---|
91 | this.defaultValue = autoStorableAttribute.DefaultValue;
|
---|
92 | }
|
---|
93 |
|
---|
94 | public DataMemberAccessor(
|
---|
95 | string name, Type type, object defaultValue,
|
---|
96 | Getter getter, Setter setter) {
|
---|
97 | this.name = name;
|
---|
98 | this.type = type;
|
---|
99 | this.defaultValue = defaultValue;
|
---|
100 | this.getter = getter;
|
---|
101 | this.setter = setter;
|
---|
102 | }
|
---|
103 |
|
---|
104 | public DataMemberAccessor(object o) {
|
---|
105 | this.name = "";
|
---|
106 | this.type = o.GetType();
|
---|
107 | this.defaultValue = null;
|
---|
108 | this.getter = () => o;
|
---|
109 | this.setter = null;
|
---|
110 | }
|
---|
111 |
|
---|
112 | public string Name {
|
---|
113 | get { return this.name; }
|
---|
114 | }
|
---|
115 |
|
---|
116 | public Type Type {
|
---|
117 | get { return this.type; }
|
---|
118 | }
|
---|
119 |
|
---|
120 | public object DefaultValue {
|
---|
121 | get { return this.defaultValue; }
|
---|
122 | }
|
---|
123 |
|
---|
124 | public object Get() {
|
---|
125 | return this.getter();
|
---|
126 | }
|
---|
127 |
|
---|
128 | public void Set(object value) {
|
---|
129 | this.setter(value);
|
---|
130 | }
|
---|
131 |
|
---|
132 | public override string ToString() {
|
---|
133 | return String.Format("DataMember({0}, {1}, {2}, {3}, {4}",
|
---|
134 | this.name,
|
---|
135 | this.type == null ? "<null>" : this.type.FullName,
|
---|
136 | this.defaultValue == null ? "<null>" : this.defaultValue,
|
---|
137 | this.getter.Method,
|
---|
138 | this.setter.Method);
|
---|
139 | }
|
---|
140 | }
|
---|
141 |
|
---|
142 |
|
---|
143 |
|
---|
144 |
|
---|
145 | }
|
---|