annotate Source/Patterns/DuckTyping.cs @ 4:f757da6161a1

!bug 100 + 2h fixed gregression
author cin
date Sun, 24 Aug 2014 17:57:42 +0400
parents f990fcb411a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1 using System;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2 using System.Collections;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Collections.Generic;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 using BLToolkit.Common;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 using BLToolkit.Properties;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7 using BLToolkit.Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8 using BLToolkit.TypeBuilder;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 using BLToolkit.TypeBuilder.Builders;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 namespace BLToolkit.Patterns
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14 /// Duck typing implementation.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 /// In computer science, duck typing is a term for dynamic typing typical
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16 /// of some programming languages, such as Smalltalk, Python or ColdFusion,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 /// where a variable's value itself determines what the variable can do.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 /// Thus an object or set of objects having all the methods described in
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 /// an interface can be made to implement that interface dynamically
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20 /// at runtime, even if the objects class does not include the interface
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21 /// in its implements clause.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 public static class DuckTyping
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25 #region Single Duck
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 static readonly Dictionary<Type,Dictionary<object,Type>> _duckTypes = new Dictionary<Type,Dictionary<object,Type>>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 /// Build a proxy type which implements the requested interface by redirecting all calls to the supplied object type.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 /// <param name="interfaceType">An interface type to implement.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 /// <param name="objectType">Any type which expected to have all members of the given interface.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34 /// <returns>The duck object type.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35 public static Type GetDuckType(Type interfaceType, Type objectType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 if (interfaceType == null) throw new ArgumentNullException("interfaceType");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38 if (!interfaceType.IsInterface) throw new ArgumentException(Resources.DuckTyping_InterfaceTypeMustBeAnInterface, "interfaceType");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 if (!interfaceType.IsPublic && !interfaceType.IsNestedPublic)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40 throw new ArgumentException(Resources.DuckTyping_InterfaceMustBePublic, "interfaceType");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 Dictionary<object,Type> types;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 lock(_duckTypes)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 if (!_duckTypes.TryGetValue(interfaceType, out types))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 _duckTypes.Add(interfaceType, types = new Dictionary<object,Type>());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 Type type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 lock (types) if (!types.TryGetValue(objectType, out type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52 type = TypeFactory.GetType(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 new CompoundValue(interfaceType, objectType),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 interfaceType, //objectType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55 new DuckTypeBuilder(MustImplementAttribute.Default, interfaceType, new[] { objectType }));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57 types.Add(objectType, type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60 return type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64 /// Implements the requested interface for supplied object.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 /// If the supplied object implements the interface, the object itself will be returned.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66 /// Otherwise a convenient duck object will be created.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 /// <param name="interfaceType">An interface type to implement.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 /// <param name="baseObjectType">Any type which has all members of the given interface.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 /// When this parameter is set to null, the object type will be used.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71 /// <param name="obj">An object which type expected to have all members of the given interface.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 /// <returns>An object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73 public static object Implement(Type interfaceType, Type baseObjectType, object obj)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 if (obj == null) throw new ArgumentNullException("obj");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77 var objType = obj.GetType();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79 if (TypeHelper.IsSameOrParent(interfaceType, objType))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 return obj;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 if (obj is DuckType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 var duckObject = (DuckType)obj;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 if (duckObject.Objects.Length == 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 // Switch to underlying objects when a duck object was passed.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 return Implement(interfaceType, baseObjectType, duckObject.Objects[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93 // Re-aggregate underlying objects to expose new interface.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95 return Aggregate(interfaceType, duckObject.Objects);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 if (baseObjectType == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99 baseObjectType = objType;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 else if (!TypeHelper.IsSameOrParent(baseObjectType, objType))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 throw new ArgumentException(string.Format(Resources.DuckTyping_NotASubtypeOf, objType.FullName, baseObjectType.FullName), "obj");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103 var duckType = GetDuckType(interfaceType, baseObjectType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 if (duckType == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108 var duck = TypeAccessor.CreateInstanceEx(duckType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110 ((DuckType)duck).SetObjects(obj);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 return duck;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 /// Implements the requested interface.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117 /// If the supplied object implements the interface, the object itself will be returned.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 /// Otherwise a convenient duck object will be created.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120 /// <param name="interfaceType">An interface type to implement.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121 /// <param name="obj">An object which type expected to have all members of the given interface.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 /// <returns>An object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 public static object Implement(Type interfaceType, object obj)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 return Implement(interfaceType, null, obj);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 /// Implements the requested interface for all supplied objects.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130 /// If any of supplied object implements the interface, the object itself will be returned.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 /// Otherwise a convenient duck object will be created.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 /// <param name="interfaceType">An interface type to implement.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 /// <param name="baseObjectType">Any type which has all members of the given interface.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135 /// When this parameter is set to null, the object type will be used.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 /// <param name="objects">An object array which types expected to have all members of the given interface.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 /// All objects may have different types.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138 /// <returns>An array of object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 public static object[] Implement(Type interfaceType, Type baseObjectType, params object[] objects)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141 if (objects == null) throw new ArgumentNullException("objects");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 object[] result = new object[objects.Length];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 for (int i = 0; i < objects.Length; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 result[i] = Implement(interfaceType, baseObjectType, objects[i]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148 return result;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152 /// Implements the requested interface for all supplied objects.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 /// If any of supplied object implements the interface, the object itself will be returned.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 /// Otherwise a convenient duck object will be created.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 /// <param name="interfaceType">An interface type to implement.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 /// <param name="objects">An object array which types expected to have all members of the given interface.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 /// All objects may have different types.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 /// <returns>An array of object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 public static object[] Implement(Type interfaceType, params object[] objects)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162 return Implement(interfaceType, (Type)null, objects);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 /// Implements the requested interface for supplied object.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 /// If the supplied object implements the interface, the object itself will be returned.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168 /// Otherwise a convenient duck object will be created.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170 /// <typeparam name="I">An interface type to implement.</typeparam>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 /// <param name="obj">An object which type expected to have all members of the given interface.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 /// <returns>An object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173 public static I Implement<I>(object obj)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174 where I : class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176 return (I)Implement(typeof(I), null, obj);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 /// Implements the requested interface for supplied object.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181 /// If the supplied object implements the interface, the object itself will be returned.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182 /// Otherwise a convenient duck object will be created.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184 /// <typeparam name="I">An interface type to implement.</typeparam>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185 /// <typeparam name="T">Any type which has all members of the given interface.</typeparam>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186 /// <param name="obj">An object which type expected to have all members of the given interface.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 /// <returns>An object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188 public static I Implement<I,T>(T obj)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189 where I : class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191 return (I)Implement(typeof(I), typeof(T), obj);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195 /// Implements the requested interface for all supplied objects.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196 /// If any of supplied object implements the interface, the object itself will be returned.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197 /// Otherwise a convenient duck object will be created.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199 /// <typeparam name="I">An interface type to implement.</typeparam>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 /// <param name="objects">An object array which types expected to have all members of the given interface.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201 /// All objects may have different types.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202 /// <returns>An array of object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203 public static I[] Implement<I>(params object[] objects)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204 where I : class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206 if (objects == null) throw new ArgumentNullException("objects");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
208 I[] result = new I[objects.Length];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
209
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
210 for (int i = 0; i < objects.Length; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
211 result[i] = Implement<I>(objects[i]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
212
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
213 return result;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
214 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
215
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
216 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
217 /// Implements the requested interface for all supplied objects.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
218 /// If any of supplied object implements the interface, the object itself will be returned.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
219 /// Otherwise a convenient duck object will be created.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
220 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
221 /// <typeparam name="I">An interface type to implement.</typeparam>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
222 /// <typeparam name="T">Any type which has all members of the given interface.</typeparam>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
223 /// <param name="objects">An object array which types expected to have all members of the given interface.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
224 /// All objects may have different types.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
225 /// <returns>An array of object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
226 public static I[] Implement<I,T>(params T[] objects)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
227 where I : class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
228 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
229 if (objects == null) throw new ArgumentNullException("objects");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
230
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
231 I[] result = new I[objects.Length];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
232
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
233 for (int i = 0; i < objects.Length; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
234 result[i] = Implement<I,T>(objects[i]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
235
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
236 return result;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
237 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
238
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
239 private static bool _allowStaticMembers;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
240 public static bool AllowStaticMembers
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
241 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
242 get { return _allowStaticMembers; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
243 set { _allowStaticMembers = value; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
244 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
245
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
246 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
247
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
248 #region Multiple Duck
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
249
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
250 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
251 /// Build a proxy type which implements the requested interface by redirecting all calls to the supplied object type.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
252 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
253 /// <param name="interfaceType">An interface type to implement.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
254 /// <param name="objectTypes">Array of types which expected to have all members of the given interface.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
255 /// <returns>The duck object type.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
256 public static Type GetDuckType(Type interfaceType, Type[] objectTypes)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
257 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
258 if (interfaceType == null) throw new ArgumentNullException("interfaceType");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
259 if (!interfaceType.IsInterface) throw new ArgumentException(Resources.DuckTyping_InterfaceTypeMustBeAnInterface, "interfaceType");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
260 if (!interfaceType.IsPublic && !interfaceType.IsNestedPublic)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
261 throw new ArgumentException(Resources.DuckTyping_InterfaceMustBePublic, "interfaceType");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
262
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
263 Dictionary<object,Type> types;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
264
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
265 lock (_duckTypes)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
266 if (!_duckTypes.TryGetValue(interfaceType, out types))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
267 _duckTypes.Add(interfaceType, types = new Dictionary<object,Type>());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
268
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
269 object key = new CompoundValue(objectTypes);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
270 Type type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
271
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
272 lock (types) if (!types.TryGetValue(key, out type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
273 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
274 type = TypeFactory.GetType(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
275 new CompoundValue(interfaceType, key),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
276 interfaceType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
277 new DuckTypeBuilder(MustImplementAttribute.Aggregate, interfaceType, objectTypes));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
278
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
279 types.Add(key, type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
280 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
281
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
282 return type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
283 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
284
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
285 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
286 /// Implements the requested interface from supplied set of objects.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
287 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
288 /// <param name="interfaceType">An interface type to implement.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
289 /// <param name="baseObjectTypes">Array of types which have all members of the given interface.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
290 /// When this parameter is set to null, the object type will be used.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
291 /// <param name="objs">Array of objects which types expected to have all members of the given interface.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
292 /// <returns>An object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
293 public static object Aggregate(Type interfaceType, Type[] baseObjectTypes,params object[] objs)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
294 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
295 if (objs == null) throw new ArgumentNullException("objs");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
296
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
297 if (baseObjectTypes == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
298 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
299 baseObjectTypes = new Type[objs.Length];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
300
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
301 for (int i = 0; i < objs.Length; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
302 if (objs[i] != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
303 baseObjectTypes[i] = objs[i].GetType();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
304 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
305 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
306 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
307 if (baseObjectTypes.Length != objs.Length)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
308 throw new ArgumentException(Resources.DuckTyping_InvalidNumberOfObjs, "baseObjectTypes");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
309
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
310 for (int i = 0; i < objs.Length; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
311 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
312 Type objType = objs[i].GetType();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
313
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
314 if (!TypeHelper.IsSameOrParent(baseObjectTypes[i], objType))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
315 throw new ArgumentException(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
316 string.Format(Resources.DuckTyping_NotASubtypeOf, objType.FullName, baseObjectTypes[i].FullName), "objs");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
317 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
318 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
319
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
320 Type duckType = GetDuckType(interfaceType, baseObjectTypes);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
321
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
322 if (duckType == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
323 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
324
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
325 object duck = TypeAccessor.CreateInstanceEx(duckType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
326
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
327 ((DuckType)duck).SetObjects(objs);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
328
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
329 return duck;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
330 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
331
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
332 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
333 /// Implements the requested interface from supplied set of objects.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
334 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
335 /// <param name="interfaceType">An interface type to implement.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
336 /// <param name="objs">Array of object which types expected to have of the given interface.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
337 /// <returns>An object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
338 public static object Aggregate(Type interfaceType,params object[] objs)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
339 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
340 return Aggregate(interfaceType, (Type[])null, objs);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
341 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
342
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
343 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
344 /// Implements the requested interface from supplied set of objects.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
345 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
346 /// <typeparam name="I">An interface type to implement.</typeparam>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
347 /// <param name="objs">Array of object which type expected to have all members of the given interface.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
348 /// <returns>An object which implements the interface.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
349 public static I Aggregate<I>(params object[] objs)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
350 where I : class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
351 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
352 return (I)Aggregate(typeof(I), null, objs);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
353 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
354
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
355 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
356 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
357 }