Skip to content

Commit 52307b3

Browse files
committed
Add [] to DynamicClass
1 parent 788569d commit 52307b3

File tree

8 files changed

+317
-24
lines changed

8 files changed

+317
-24
lines changed

System.Linq.Dynamic.Core.sln

+19
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GroupByError.Fixed.Microsof
7171
{CE1620BD-A313-4223-B991-467DA346B2ED} = {CE1620BD-A313-4223-B991-467DA346B2ED}
7272
EndProjectSection
7373
EndProject
74+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DynamicLinqWebDocs", "web\DynamicLinqWebDocs\DynamicLinqWebDocs.csproj", "{1942BDB5-CDA0-4B50-85BD-D726303F219C}"
75+
EndProject
7476
Global
7577
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7678
Debug|Any CPU = Debug|Any CPU
@@ -331,6 +333,22 @@ Global
331333
{FC2BC135-D17D-4F7E-847E-3AC2882E2EC1}.Release|x64.Build.0 = Release|Any CPU
332334
{FC2BC135-D17D-4F7E-847E-3AC2882E2EC1}.Release|x86.ActiveCfg = Release|Any CPU
333335
{FC2BC135-D17D-4F7E-847E-3AC2882E2EC1}.Release|x86.Build.0 = Release|Any CPU
336+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
337+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Debug|Any CPU.Build.0 = Debug|Any CPU
338+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Debug|ARM.ActiveCfg = Debug|Any CPU
339+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Debug|ARM.Build.0 = Debug|Any CPU
340+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Debug|x64.ActiveCfg = Debug|Any CPU
341+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Debug|x64.Build.0 = Debug|Any CPU
342+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Debug|x86.ActiveCfg = Debug|Any CPU
343+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Debug|x86.Build.0 = Debug|Any CPU
344+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Release|Any CPU.ActiveCfg = Release|Any CPU
345+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Release|Any CPU.Build.0 = Release|Any CPU
346+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Release|ARM.ActiveCfg = Release|Any CPU
347+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Release|ARM.Build.0 = Release|Any CPU
348+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Release|x64.ActiveCfg = Release|Any CPU
349+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Release|x64.Build.0 = Release|Any CPU
350+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Release|x86.ActiveCfg = Release|Any CPU
351+
{1942BDB5-CDA0-4B50-85BD-D726303F219C}.Release|x86.Build.0 = Release|Any CPU
334352
EndGlobalSection
335353
GlobalSection(SolutionProperties) = preSolution
336354
HideSolutionNode = FALSE
@@ -351,5 +369,6 @@ Global
351369
{E9AD2D32-E69F-4F81-A6F4-AF0C27F0410C} = {2EF50FA7-4E0A-4029-8864-765C3C76F9CA}
352370
{33E3A9DB-EB1A-4F8B-867E-55E31EE5FD5A} = {E43ECBC5-D65A-4EE3-AF5D-5F74E9A4009A}
353371
{FC2BC135-D17D-4F7E-847E-3AC2882E2EC1} = {C98BB543-9BDA-4EE3-927D-0F10CC24A49B}
372+
{1942BDB5-CDA0-4B50-85BD-D726303F219C} = {2EF50FA7-4E0A-4029-8864-765C3C76F9CA}
354373
EndGlobalSection
355374
EndGlobal

src-console/System.Linq.Dynamic.Core.ConsoleTestApp/Program.cs

+11-4
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,21 @@ public static void Main(string[] args)
3636
{
3737
Console.WriteLine("--start");
3838

39-
DynamicProperty[] props = new DynamicProperty[] { new DynamicProperty("Name", typeof(string)), new DynamicProperty("Birthday", typeof(DateTime)) };
39+
DynamicProperty[] props = { new DynamicProperty("Name", typeof(string)), new DynamicProperty("Birthday", typeof(DateTime)) };
4040
Type type = DynamicClassFactory.CreateType(props);
4141
DynamicClass dynamicClass = Activator.CreateInstance(type) as DynamicClass;
42-
dynamicClass.SetDynamicProperty("Name", "Albert");
43-
dynamicClass.SetDynamicProperty("Birthday", new DateTime(1879, 3, 14));
42+
dynamicClass.SetDynamicPropertyValue("Name", "Albert");
43+
dynamicClass.SetDynamicPropertyValue("Birthday", new DateTime(1879, 3, 14));
4444
Console.WriteLine(dynamicClass);
4545

46-
GroupByAndSelect_TestDynamicSelectMember();
46+
string n1 = dynamicClass["Name"] as string;
47+
Console.WriteLine("dynamicClass[\"Name\"] = '" + n1 + "'");
48+
49+
dynamicClass["NameX"] = "x";
50+
string n2 = dynamicClass["NameX"] as string;
51+
Console.WriteLine("dynamicClass[\"NameX\"] = '" + n2 + "'");
52+
53+
//GroupByAndSelect_TestDynamicSelectMember();
4754
//Select();
4855
//TestDyn();
4956
//ExpressionTests_Enum();

src/System.Linq.Dynamic.Core/DynamicClass.cs

+168-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
#if UAP10_0
1+
using System.Collections;
22
using System.Collections.Generic;
3+
using System.Reflection;
4+
5+
#if UAP10_0
36
using System.Dynamic;
47

58
namespace System.Linq.Dynamic.Core
@@ -97,10 +100,66 @@ public override bool TrySetMember(SetMemberBinder binder, object value)
97100
}
98101
}
99102
}
103+
# elif NET35
104+
namespace System.Linq.Dynamic.Core
105+
{
106+
/// <summary>
107+
/// Provides a base class for dynamic objects for Net 3.5
108+
/// </summary>
109+
public abstract class DynamicClass
110+
{
111+
/// <summary>
112+
/// Gets the dynamic property by name.
113+
/// </summary>
114+
/// <typeparam name="T">The type.</typeparam>
115+
/// <param name="propertyName">Name of the property.</param>
116+
/// <returns>T</returns>
117+
public T GetDynamicPropertyValue<T>(string propertyName)
118+
{
119+
var type = GetType();
120+
var propInfo = type.GetProperty(propertyName);
121+
122+
return (T)propInfo.GetValue(this, null);
123+
}
124+
125+
/// <summary>
126+
/// Gets the dynamic property value by name.
127+
/// </summary>
128+
/// <param name="propertyName">Name of the property.</param>
129+
/// <returns>value</returns>
130+
public object GetDynamicPropertyValue(string propertyName)
131+
{
132+
return GetDynamicPropertyValue<object>(propertyName);
133+
}
134+
135+
/// <summary>
136+
/// Sets the dynamic property value by name.
137+
/// </summary>
138+
/// <typeparam name="T">The type.</typeparam>
139+
/// <param name="propertyName">Name of the property.</param>
140+
/// <param name="value">The value.</param>
141+
public void SetDynamicPropertyValue<T>(string propertyName, T value)
142+
{
143+
var type = GetType();
144+
var propInfo = type.GetProperty(propertyName);
145+
146+
propInfo.SetValue(this, value, null);
147+
}
148+
149+
/// <summary>
150+
/// Sets the dynamic property value by name.
151+
/// </summary>
152+
/// <param name="propertyName">Name of the property.</param>
153+
/// <param name="value">The value.</param>
154+
public void SetDynamicPropertyValue(string propertyName, object value)
155+
{
156+
SetDynamicPropertyValue<object>(propertyName, value);
157+
}
158+
}
159+
}
100160
#else
101-
#if WINDOWS_APP || DOTNET5_1 || NETSTANDARD
102-
using System.Reflection;
103-
#endif
161+
using System.Dynamic;
162+
104163
namespace System.Linq.Dynamic.Core
105164
{
106165
/// <summary>
@@ -114,15 +173,37 @@ namespace System.Linq.Dynamic.Core
114173
/// - Equals() method
115174
/// - GetHashCode() method
116175
/// </summary>
117-
public abstract class DynamicClass
176+
public abstract class DynamicClass : DynamicObject
118177
{
178+
private Dictionary<string, object> _propertiesDictionary;
179+
180+
private Dictionary<string, object> _properties
181+
{
182+
get
183+
{
184+
if (_propertiesDictionary == null)
185+
{
186+
_propertiesDictionary = new Dictionary<string, object>();
187+
188+
foreach (PropertyInfo pi in GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
189+
{
190+
int parameters = pi.GetGetMethod().GetParameters().Length;
191+
if (parameters == 0)
192+
_propertiesDictionary.Add(pi.Name, pi.GetValue(this, null));
193+
}
194+
}
195+
196+
return _propertiesDictionary;
197+
}
198+
}
199+
119200
/// <summary>
120201
/// Gets the dynamic property by name.
121202
/// </summary>
122203
/// <typeparam name="T">The type.</typeparam>
123204
/// <param name="propertyName">Name of the property.</param>
124205
/// <returns>T</returns>
125-
public T GetDynamicProperty<T>(string propertyName)
206+
public T GetDynamicPropertyValue<T>(string propertyName)
126207
{
127208
var type = GetType();
128209
var propInfo = type.GetProperty(propertyName);
@@ -131,22 +212,22 @@ public T GetDynamicProperty<T>(string propertyName)
131212
}
132213

133214
/// <summary>
134-
/// Gets the dynamic property by name.
215+
/// Gets the dynamic property value by name.
135216
/// </summary>
136217
/// <param name="propertyName">Name of the property.</param>
137218
/// <returns>value</returns>
138-
public object GetDynamicProperty(string propertyName)
219+
public object GetDynamicPropertyValue(string propertyName)
139220
{
140-
return GetDynamicProperty<object>(propertyName);
221+
return GetDynamicPropertyValue<object>(propertyName);
141222
}
142223

143224
/// <summary>
144-
/// Sets the dynamic property by name.
225+
/// Sets the dynamic property value by name.
145226
/// </summary>
146227
/// <typeparam name="T">The type.</typeparam>
147228
/// <param name="propertyName">Name of the property.</param>
148229
/// <param name="value">The value.</param>
149-
public void SetDynamicProperty<T>(string propertyName, T value)
230+
public void SetDynamicPropertyValue<T>(string propertyName, T value)
150231
{
151232
var type = GetType();
152233
var propInfo = type.GetProperty(propertyName);
@@ -155,16 +236,87 @@ public void SetDynamicProperty<T>(string propertyName, T value)
155236
}
156237

157238
/// <summary>
158-
/// Sets the dynamic property by name.
239+
/// Sets the dynamic property value by name.
159240
/// </summary>
160241
/// <param name="propertyName">Name of the property.</param>
161242
/// <param name="value">The value.</param>
162-
public void SetDynamicProperty(string propertyName, object value)
243+
public void SetDynamicPropertyValue(string propertyName, object value)
163244
{
164-
var type = GetType();
165-
var propInfo = type.GetProperty(propertyName);
245+
SetDynamicPropertyValue<object>(propertyName, value);
246+
}
166247

167-
propInfo.SetValue(this, value, null);
248+
/// <summary>
249+
/// Gets or sets the <see cref="object"/> with the specified name.
250+
/// </summary>
251+
/// <value>
252+
/// The <see cref="object"/>.
253+
/// </value>
254+
/// <param name="name">The name.</param>
255+
/// <returns>Value from the property.</returns>
256+
public object this[string name]
257+
{
258+
get
259+
{
260+
object result;
261+
if (_properties.TryGetValue(name, out result))
262+
return result;
263+
264+
return null;
265+
}
266+
267+
set
268+
{
269+
if (_properties.ContainsKey(name))
270+
_properties[name] = value;
271+
else
272+
_properties.Add(name, value);
273+
}
274+
}
275+
276+
/// <summary>
277+
/// Returns the enumeration of all dynamic member names.
278+
/// </summary>
279+
/// <returns>
280+
/// A sequence that contains dynamic member names.
281+
/// </returns>
282+
public override IEnumerable<string> GetDynamicMemberNames()
283+
{
284+
return _properties.Keys;
285+
}
286+
287+
/// <summary>
288+
/// Provides the implementation for operations that get member values. Classes derived from the <see cref="T:System.Dynamic.DynamicObject" /> class can override this method to specify dynamic behavior for operations such as getting a value for a property.
289+
/// </summary>
290+
/// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Name property provides the name of the member on which the dynamic operation is performed. For example, for the Console.WriteLine(sampleObject.SampleProperty) statement, where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject" /> class, binder.Name returns "SampleProperty". The binder.IgnoreCase property specifies whether the member name is case-sensitive.</param>
291+
/// <param name="result">The result of the get operation. For example, if the method is called for a property, you can assign the property value to <paramref name="result" />.</param>
292+
/// <returns>
293+
/// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of the language determines the behavior. (In most cases, a run-time exception is thrown.)
294+
/// </returns>
295+
public override bool TryGetMember(GetMemberBinder binder, out object result)
296+
{
297+
string name = binder.Name;
298+
_properties.TryGetValue(name, out result);
299+
300+
return true;
301+
}
302+
303+
/// <summary>
304+
/// Provides the implementation for operations that set member values. Classes derived from the <see cref="T:System.Dynamic.DynamicObject" /> class can override this method to specify dynamic behavior for operations such as setting a value for a property.
305+
/// </summary>
306+
/// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Name property provides the name of the member to which the value is being assigned. For example, for the statement sampleObject.SampleProperty = "Test", where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject" /> class, binder.Name returns "SampleProperty". The binder.IgnoreCase property specifies whether the member name is case-sensitive.</param>
307+
/// <param name="value">The value to set to the member. For example, for sampleObject.SampleProperty = "Test", where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject" /> class, the <paramref name="value" /> is "Test".</param>
308+
/// <returns>
309+
/// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of the language determines the behavior. (In most cases, a language-specific run-time exception is thrown.)
310+
/// </returns>
311+
public override bool TrySetMember(SetMemberBinder binder, object value)
312+
{
313+
string name = binder.Name;
314+
if (_properties.ContainsKey(name))
315+
_properties[name] = value;
316+
else
317+
_properties.Add(name, value);
318+
319+
return true;
168320
}
169321
}
170322
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//#if !(NET35 || UAP10_0)
2+
//using System.Dynamic;
3+
//using System.Reflection;
4+
//using JetBrains.Annotations;
5+
6+
//namespace System.Linq.Dynamic.Core.Extensions
7+
//{
8+
// public static class ExpandObjectExtensions
9+
// {
10+
// public static DynamicClass ToDynamicClass([NotNull] this object obj, bool createParameterCtor = true)
11+
// {
12+
// var propertyInfo = obj.GetType().GetProperties();
13+
// var dynamicProperties = propertyInfo.Select(p => new DynamicProperty(p.Name, p.PropertyType)).ToList();
14+
15+
// Type type = DynamicClassFactory.CreateType(dynamicProperties, createParameterCtor);
16+
// var dynamicClass = (DynamicClass) Activator.CreateInstance(type);
17+
18+
// foreach (var kvp in obj)
19+
// dynamicClass.SetDynamicPropertyValue(kvp.Key, kvp.Value);
20+
21+
// return dynamicClass;
22+
// }
23+
// }
24+
//}
25+
//#endif

src/System.Linq.Dynamic.Core/project.json

+3
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"System.Linq": "4.0.0",
7171
"System.Linq.Expressions": "4.0.0",
7272
"System.Linq.Queryable": "4.0.0",
73+
"System.ObjectModel": "4.0.0",
7374
"System.Reflection.Emit": "4.0.0",
7475
"System.Reflection.TypeExtensions": "4.0.0",
7576
"System.Runtime": "4.0.20",
@@ -85,6 +86,7 @@
8586
"System.Linq": "4.0.0",
8687
"System.Linq.Expressions": "4.0.0",
8788
"System.Linq.Queryable": "4.0.0",
89+
"System.ObjectModel": "4.0.0",
8890
"System.Reflection.Emit": "4.0.0",
8991
"System.Reflection.TypeExtensions": "4.0.0",
9092
"System.Runtime": "4.0.20",
@@ -122,6 +124,7 @@
122124
"System.Globalization": "4.0.11",
123125
"System.Linq.Expressions": "4.1.0",
124126
"System.Linq.Queryable": "4.0.1",
127+
"System.ObjectModel": "4.0.12",
125128
"System.Reflection.Emit": "4.0.1",
126129
"System.Reflection.TypeExtensions": "4.1.0",
127130
"System.Runtime.Extensions": "4.1.0",

0 commit comments

Comments
 (0)