Skip to content

Commit 5df1fde

Browse files
committed
Add ability to use dynamic component in any format
1 parent 128e336 commit 5df1fde

File tree

15 files changed

+501
-75
lines changed

15 files changed

+501
-75
lines changed

doc/reference/modules/basic_mapping.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2680,9 +2680,10 @@
26802680
</para>
26812681

26822682
<para>
2683-
The <literal>&lt;dynamic-component&gt;</literal> element allows an <literal>IDictionary</literal>
2684-
or <literal>IDictionary&lt;string, object&gt;</literal> to be mapped as a component, where the
2685-
property names refer to keys of the dictionary. See <xref linkend="components-dynamic" />.
2683+
The <literal>&lt;dynamic-component&gt;</literal> element allows an <literal>IDictionary</literal>,
2684+
<literal>IDictionary&lt;string, object&gt;</literal>, or a C# <literal>dynamic</literal> to be mapped
2685+
as a component. When using dictionaries, the property names refer to keys of the dictionary. See
2686+
<xref linkend="components-dynamic" />.
26862687
</para>
26872688

26882689
</sect2>

doc/reference/modules/component_mapping.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,8 @@
342342

343343
<para>
344344
You can also map a property of type <literal>IDictionary</literal> or
345-
<literal>IDictionary&lt;string, object&gt;</literal>:
345+
<literal>IDictionary&lt;string, object&gt;</literal>, or declared as a C#
346+
<literal>dynamic</literal>:
346347
</para>
347348

348349
<programlisting><![CDATA[<dynamic-component name="UserAttributes">
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System;
12+
using System.Collections.Generic;
13+
using NUnit.Framework;
14+
15+
namespace NHibernate.Test.NHSpecificTest.NH1039Dynamic
16+
{
17+
using System.Threading.Tasks;
18+
[TestFixture]
19+
public class FixtureAsync : BugTestCase
20+
{
21+
protected override void OnTearDown()
22+
{
23+
using (var s = OpenSession())
24+
using (var tx = s.BeginTransaction())
25+
{
26+
s.Delete("from Person");
27+
tx.Commit();
28+
}
29+
}
30+
31+
[Test]
32+
public async Task TestAsync()
33+
{
34+
using (var s = OpenSession())
35+
using (var tx = s.BeginTransaction())
36+
{
37+
var person = new Person("1")
38+
{
39+
Name = "John Doe",
40+
Properties =
41+
{
42+
Phones = new HashSet<object> {"555-1234", "555-4321"}
43+
}
44+
};
45+
46+
await (s.SaveAsync(person));
47+
await (tx.CommitAsync());
48+
}
49+
50+
using (var s = OpenSession())
51+
using (s.BeginTransaction())
52+
{
53+
var person = (Person) await (s.CreateCriteria(typeof(Person)).UniqueResultAsync());
54+
55+
Assert.That(person.ID, Is.EqualTo("1"));
56+
Assert.That(person.Name, Is.EqualTo("John Doe"));
57+
var phones = person.Properties.Phones as ISet<object>;
58+
Assert.That(phones, Is.Not.Null);
59+
Assert.That(phones.Contains("555-1234"), Is.True);
60+
Assert.That(phones.Contains("555-4321"), Is.True);
61+
}
62+
}
63+
}
64+
}

src/NHibernate.Test/Async/NHSpecificTest/NH2664Dynamic/Fixture.cs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.Linq;
1313
using NUnit.Framework;
1414
using System.Collections.Generic;
15+
using System.Dynamic;
1516
using System.Linq.Dynamic.Core;
1617
using NHibernate.Linq;
1718

@@ -34,37 +35,38 @@ protected override void OnSetUp()
3435
using (var session = OpenSession())
3536
using (var tran = session.BeginTransaction())
3637
{
38+
var properties1 = new Dictionary<string, object>
39+
{
40+
["Name"] = "First Product",
41+
["Description"] = "First Description"
42+
};
3743
session.Save(
3844
new Product
3945
{
4046
ProductId = "1",
41-
Properties = new Dictionary<string, object>
42-
{
43-
["Name"] = "First Product",
44-
["Description"] = "First Description"
45-
}
47+
Properties = properties1
4648
});
4749

50+
var properties2 = new
51+
{
52+
Name = "Second Product",
53+
Description = "Second Description"
54+
};
4855
session.Save(
4956
new Product
5057
{
5158
ProductId = "2",
52-
Properties = new Dictionary<string, object>
53-
{
54-
["Name"] = "Second Product",
55-
["Description"] = "Second Description"
56-
}
59+
Properties = properties2
5760
});
5861

62+
dynamic properties3 = new ExpandoObject();
63+
properties3.Name = "Third Product";
64+
properties3.Description = "Third Description";
5965
session.Save(
6066
new Product
6167
{
6268
ProductId = "3",
63-
Properties = new Dictionary<string, object>
64-
{
65-
["Name"] = "val",
66-
["Description"] = "val"
67-
}
69+
Properties = properties3
6870
});
6971

7072
tran.Commit();
@@ -93,6 +95,7 @@ public async Task Query_DynamicComponentAsync()
9395

9496
Assert.That(product, Is.Not.Null);
9597
Assert.That((object) product.Properties["Name"], Is.EqualTo("First Product"));
98+
Assert.That((object) product.Properties.Name, Is.EqualTo("First Product"));
9699
}
97100
}
98101

@@ -112,4 +115,4 @@ public async Task Multiple_Query_Does_Not_CacheAsync()
112115
}
113116
}
114117
}
115-
}
118+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using NUnit.Framework;
4+
5+
namespace NHibernate.Test.NHSpecificTest.NH1039Dynamic
6+
{
7+
[TestFixture]
8+
public class Fixture : BugTestCase
9+
{
10+
protected override void OnTearDown()
11+
{
12+
using (var s = OpenSession())
13+
using (var tx = s.BeginTransaction())
14+
{
15+
s.Delete("from Person");
16+
tx.Commit();
17+
}
18+
}
19+
20+
[Test]
21+
public void Test()
22+
{
23+
using (var s = OpenSession())
24+
using (var tx = s.BeginTransaction())
25+
{
26+
var person = new Person("1")
27+
{
28+
Name = "John Doe",
29+
Properties =
30+
{
31+
Phones = new HashSet<object> {"555-1234", "555-4321"}
32+
}
33+
};
34+
35+
s.Save(person);
36+
tx.Commit();
37+
}
38+
39+
using (var s = OpenSession())
40+
using (s.BeginTransaction())
41+
{
42+
var person = (Person) s.CreateCriteria(typeof(Person)).UniqueResult();
43+
44+
Assert.That(person.ID, Is.EqualTo("1"));
45+
Assert.That(person.Name, Is.EqualTo("John Doe"));
46+
var phones = person.Properties.Phones as ISet<object>;
47+
Assert.That(phones, Is.Not.Null);
48+
Assert.That(phones.Contains("555-1234"), Is.True);
49+
Assert.That(phones.Contains("555-4321"), Is.True);
50+
}
51+
}
52+
}
53+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
3+
namespace="NHibernate.Test.NHSpecificTest.NH1039Dynamic"
4+
assembly="NHibernate.Test">
5+
6+
<class name="Person" table="NH1039_Person">
7+
<id name="ID" type="string" length="32">
8+
<generator class="assigned"/>
9+
</id>
10+
11+
<property name="Name"/>
12+
13+
<dynamic-component name="Properties">
14+
<set name="Phones" table="NH1039_Phone">
15+
<key column="PersonId"/>
16+
<element column="`Number`" type="string"/>
17+
</set>
18+
</dynamic-component>
19+
</class>
20+
21+
</hibernate-mapping>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Dynamic;
5+
using System.Text;
6+
7+
namespace NHibernate.Test.NHSpecificTest.NH1039Dynamic
8+
{
9+
public class Person
10+
{
11+
public Person()
12+
{
13+
}
14+
15+
public Person(string id)
16+
{
17+
ID = id;
18+
}
19+
20+
public virtual string ID { get; set; }
21+
22+
public virtual string Name { get; set; }
23+
24+
public virtual dynamic Properties { get; set; } = new ExpandoObject();
25+
}
26+
}

src/NHibernate.Test/NHSpecificTest/NH2664Dynamic/Fixture.cs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using NUnit.Framework;
44
using System.Collections.Generic;
5+
using System.Dynamic;
56
using System.Linq.Dynamic.Core;
67

78
namespace NHibernate.Test.NHSpecificTest.NH2664Dynamic
@@ -22,37 +23,38 @@ protected override void OnSetUp()
2223
using (var session = OpenSession())
2324
using (var tran = session.BeginTransaction())
2425
{
26+
var properties1 = new Dictionary<string, object>
27+
{
28+
["Name"] = "First Product",
29+
["Description"] = "First Description"
30+
};
2531
session.Save(
2632
new Product
2733
{
2834
ProductId = "1",
29-
Properties = new Dictionary<string, object>
30-
{
31-
["Name"] = "First Product",
32-
["Description"] = "First Description"
33-
}
35+
Properties = properties1
3436
});
3537

38+
var properties2 = new
39+
{
40+
Name = "Second Product",
41+
Description = "Second Description"
42+
};
3643
session.Save(
3744
new Product
3845
{
3946
ProductId = "2",
40-
Properties = new Dictionary<string, object>
41-
{
42-
["Name"] = "Second Product",
43-
["Description"] = "Second Description"
44-
}
47+
Properties = properties2
4548
});
4649

50+
dynamic properties3 = new ExpandoObject();
51+
properties3.Name = "Third Product";
52+
properties3.Description = "Third Description";
4753
session.Save(
4854
new Product
4955
{
5056
ProductId = "3",
51-
Properties = new Dictionary<string, object>
52-
{
53-
["Name"] = "val",
54-
["Description"] = "val"
55-
}
57+
Properties = properties3
5658
});
5759

5860
tran.Commit();
@@ -81,6 +83,7 @@ public void Query_DynamicComponent()
8183

8284
Assert.That(product, Is.Not.Null);
8385
Assert.That((object) product.Properties["Name"], Is.EqualTo("First Product"));
86+
Assert.That((object) product.Properties.Name, Is.EqualTo("First Product"));
8487
}
8588
}
8689

@@ -100,4 +103,4 @@ public void Multiple_Query_Does_Not_Cache()
100103
}
101104
}
102105
}
103-
}
106+
}

src/NHibernate.Test/NHSpecificTest/NH2664Dynamic/Mappings.hbm.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414

1515
</class>
1616

17-
</hibernate-mapping>
17+
</hibernate-mapping>

src/NHibernate.Test/NHSpecificTest/NH2664Dynamic/Product.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ public class Product
66

77
public virtual dynamic Properties { get; set; }
88
}
9-
}
9+
}

src/NHibernate/NHibernate.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<Reference Include="System.ServiceModel" />
5050
<Reference Include="System.Transactions" />
5151
<Reference Include="System.Configuration" />
52+
<Reference Include="Microsoft.CSharp" />
5253
</ItemGroup>
5354

5455
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
@@ -59,6 +60,7 @@
5960
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.4.1" />
6061
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
6162
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
63+
<PackageReference Include="Microsoft.CSharp" Version="4.4.1" />
6264
</ItemGroup>
6365

6466
<ItemGroup>

0 commit comments

Comments
 (0)