Skip to content

Commit 184e6f7

Browse files
committed
now, simple EF Core queries can run correctly.
1 parent 5126b97 commit 184e6f7

File tree

7 files changed

+153
-56
lines changed

7 files changed

+153
-56
lines changed

DeepCloner.Tests/SpecificScenariosTest.cs

Lines changed: 91 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
using System.Globalization;
1111
using System.Linq;
1212
using System.Runtime.InteropServices;
13-
1413
using NUnit.Framework;
1514

1615
namespace Force.DeepCloner.Tests
@@ -48,9 +47,27 @@ public void Test_ExpressionTree_OrderBy2()
4847
[Test(Description = "Tests works on local SQL Server with AdventureWorks database")]
4948
public void Clone_EfQuery1()
5049
{
51-
var q = new AdventureContext().Currencies.Where(x => x.CurrencyCode == "AUD");
50+
var at = new AdventureContext();
51+
// var at2 = at.DeepClone();
52+
// Console.WriteLine(at.ChangeTracker);
53+
// Console.WriteLine(at.ChangeTracker);
54+
var q = at.Currencies.Where(x => x.CurrencyCode == "AUD");
5255
var q2 = q.DeepClone();
53-
Assert.That(q.ToArray().Length, Is.EqualTo(1));
56+
#if NETCORE
57+
// Console.WriteLine(Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions
58+
// .GetRequiredService<Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IChangeTrackerFactory>(
59+
// ((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<IServiceProvider>) at).Instance));
60+
/* Console.WriteLine(((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<IServiceProvider>) at).Instance);
61+
var serviceProvider = ((Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<IServiceProvider>) at.DeepClone()).Instance;
62+
Console.WriteLine(serviceProvider);
63+
Console.WriteLine(serviceProvider.GetService(typeof(Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IChangeTrackerFactory)));
64+
Console.WriteLine(Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions
65+
.GetRequiredService<Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IChangeTrackerFactory>(
66+
serviceProvider));*/
67+
#endif
68+
// var q2 = q.DeepClone();
69+
// Console.WriteLine(q2.);
70+
// Assert.That(q.ToArray().Length, Is.EqualTo(1));
5471
Assert.That(q2.ToArray().Length, Is.EqualTo(1));
5572
}
5673

@@ -59,7 +76,7 @@ public void Clone_EfQuery2()
5976
{
6077
var q = new AdventureContext().Currencies.OrderBy(x => x.Name);
6178
var q2 = q.DeepClone();
62-
var cnt = q2.Count();
79+
var cnt = q.Count();
6380
Assert.That(q2.Count(), Is.EqualTo(cnt));
6481
}
6582

@@ -70,11 +87,11 @@ public void Clone_ComObject1()
7087
// ReSharper disable SuspiciousTypeConversion.Global
7188
var manager = (KnownFolders.IKnownFolderManager)new KnownFolders.KnownFolderManager();
7289
// ReSharper restore SuspiciousTypeConversion.Global
73-
Guid knownFolderID1;
74-
Guid knownFolderID2;
75-
manager.FolderIdFromCsidl(0, out knownFolderID1);
76-
manager.DeepClone().FolderIdFromCsidl(0, out knownFolderID2);
77-
Assert.That(knownFolderID1, Is.EqualTo(knownFolderID2));
90+
Guid knownFolderId1;
91+
Guid knownFolderId2;
92+
manager.FolderIdFromCsidl(0, out knownFolderId1);
93+
manager.DeepClone().FolderIdFromCsidl(0, out knownFolderId2);
94+
Assert.That(knownFolderId1, Is.EqualTo(knownFolderId2));
7895
#endif
7996
}
8097

@@ -88,6 +105,28 @@ public void Clone_ComObject2()
88105
#endif
89106
}
90107

108+
[Test]
109+
public void Lazy_Clone()
110+
{
111+
var lazy = new LazyClass();
112+
var clone = lazy.DeepClone();
113+
var v = LazyClass.Counter;
114+
Assert.That(clone.GetValue(), Is.EqualTo((v + 1).ToString(CultureInfo.InvariantCulture)));
115+
Assert.That(lazy.GetValue(), Is.EqualTo((v + 2).ToString(CultureInfo.InvariantCulture)));
116+
}
117+
118+
public class LazyClass
119+
{
120+
public static int Counter;
121+
122+
private readonly LazyRef<object> _lazyValue = new LazyRef<object>(() => (object)(++Counter).ToString(CultureInfo.InvariantCulture));
123+
124+
public string GetValue()
125+
{
126+
return _lazyValue.Value.ToString();
127+
}
128+
}
129+
91130
[Table("Currency", Schema = "Sales")]
92131
public class Currency
93132
{
@@ -124,6 +163,17 @@ public void GenericComparer_Clone()
124163
comparer.DeepClone();
125164
}
126165

166+
[Test]
167+
public void Closure_Clone()
168+
{
169+
int a = 0;
170+
Func<int> f = () => ++a;
171+
var fCopy = f.DeepClone();
172+
Assert.That(f(), Is.EqualTo(1));
173+
Assert.That(fCopy(), Is.EqualTo(1));
174+
Assert.That(a, Is.EqualTo(1));
175+
}
176+
127177
private class TestComparer : Comparer<int>
128178
{
129179
// make object unsafe to work
@@ -158,5 +208,37 @@ internal class KnownFolderManager
158208
}
159209
}
160210
#endif
211+
public sealed class LazyRef<T>
212+
{
213+
private Func<T> _initializer;
214+
private T _value;
215+
216+
/// <summary>
217+
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
218+
/// directly from your code. This API may change or be removed in future releases.
219+
/// </summary>
220+
public T Value
221+
{
222+
get
223+
{
224+
if (_initializer != null)
225+
{
226+
_value = _initializer();
227+
_initializer = null;
228+
}
229+
return _value;
230+
}
231+
set
232+
{
233+
_value = value;
234+
_initializer = null;
235+
}
236+
}
237+
238+
public LazyRef(Func<T> initializer)
239+
{
240+
_initializer = initializer;
241+
}
242+
}
161243
}
162244
}

DeepCloner.Tests/project.json

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,46 @@
11
{
2-
"version": "1.0.0-*",
3-
"buildOptions": {
4-
"debugType": "portable",
5-
"allowUnsafe": true
6-
},
7-
"dependencies": {
8-
"DeepCloner": "*",
9-
"NUnit": "3.6.0"
10-
},
2+
"version": "1.0.0-*",
3+
"buildOptions": {
4+
"debugType": "portable",
5+
"allowUnsafe": true
6+
},
7+
"dependencies": {
8+
"DeepCloner": "0.10.1",
9+
"NUnit": "3.6.0"
10+
},
1111

12-
"testRunner": "nunit",
12+
"testRunner": "nunit",
1313

14-
"frameworks": {
15-
"net461": {
16-
"dependencies": {
17-
"Clone.Behave": "1.0.1",
18-
"CloneExtensions": "1.2",
19-
"GeorgeCloney": "1.1.2.20",
20-
"NClone": "1.1.1",
21-
"Nuclex.Cloning": "1.0.0",
22-
"FastDeepCloner": "1.0.9",
23-
"DesertOctopus": "0.1.1",
24-
"EntityFramework": "6.1.3"
25-
},
26-
"frameworkAssemblies": {
27-
"System.ComponentModel.DataAnnotations": "4.0.0"
28-
}
29-
},
30-
"netcoreapp1.0": {
31-
"imports": "portable-net45+win8",
32-
"buildOptions": {
33-
"define": ["NETCORE"]
34-
},
35-
"dependencies": {
36-
"NETStandard.Library": "1.6.1",
37-
"Microsoft.EntityFrameworkCore.SqlServer": "1.1.2",
38-
"dotnet-test-nunit": "3.4.0-beta-3",
39-
"Microsoft.NETCore.App": {
40-
"version": "1.1.0-*",
41-
"type": "platform"
42-
}
43-
}
44-
}
45-
}
14+
"frameworks": {
15+
"net461": {
16+
"dependencies": {
17+
"Clone.Behave": "1.0.1",
18+
"CloneExtensions": "1.2",
19+
"GeorgeCloney": "1.1.2.20",
20+
"NClone": "1.1.1",
21+
"Nuclex.Cloning": "1.0.0",
22+
"FastDeepCloner": "1.0.9",
23+
"DesertOctopus": "0.1.1",
24+
"EntityFramework": "6.1.3"
25+
},
26+
"frameworkAssemblies": {
27+
"System.ComponentModel.DataAnnotations": "4.0.0"
28+
}
29+
},
30+
"netcoreapp1.0": {
31+
"imports": "portable-net45+win8",
32+
"buildOptions": {
33+
"define": ["NETCORE"]
34+
},
35+
"dependencies": {
36+
"NETStandard.Library": "1.6.1",
37+
"Microsoft.EntityFrameworkCore.SqlServer": "1.1.2",
38+
"dotnet-test-nunit": "3.4.0-beta-3",
39+
"Microsoft.NETCore.App": {
40+
"version": "1.1.0-*",
41+
"type": "platform"
42+
}
43+
}
44+
}
45+
}
4646
}

DeepCloner.nuspec

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<metadata>
44
<id>DeepCloner</id>
55
<title>DeepCloner</title>
6-
<version>0.10.0</version>
6+
<version>0.10.1</version>
77
<authors>force</authors>
88
<owners>force</owners>
99
<licenseUrl>https://github.com/force-net/DeepCloner/blob/develop/LICENSE</licenseUrl>
@@ -12,7 +12,8 @@
1212
<requireLicenseAcceptance>false</requireLicenseAcceptance>
1313
<description>Small Library for fast deep or shallow cloning .NET objects. It allows to copy everything and has a lot of performance tricks for fast copying.</description>
1414
<releaseNotes>
15-
Added additional methods for cloning DeepCloneTo/ShallowCloneTo
15+
Fixed cloning of COM objects, some internal structures (RuntimeType, Remoting). Trying to improve cloning for dotnet core, excluded some internal classes.
16+
As result, some EF queries can be deep cloned without errors.
1617
</releaseNotes>
1718
<copyright>Copyright by Force 2016-2017</copyright>
1819
<tags>.NET shallow deep clone DeepClone fast</tags>

DeepCloner/Helpers/DeepClonerMsilGenerator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ internal static class DeepClonerMsilGenerator
1313

1414
internal static object GenerateClonerInternal(Type realType, bool asObject)
1515
{
16+
// Console.WriteLine(realType.FullName);
1617
// there is no performance penalties to cast objects to concrete type, but we can win in removing other conversions
1718
var methodType = asObject ? typeof(object) : realType;
1819

DeepCloner/Helpers/DeepClonerSafeTypes.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ internal static bool IsTypeSafe(Type type, HashSet<Type> processingTypes)
7171
KnownTypes.TryAdd(type, true);
7272
return true;
7373
}
74+
75+
// better not to touch ms dependency injection
76+
if (type.FullName.StartsWith("Microsoft.Extensions.DependencyInjection."))
77+
{
78+
KnownTypes.TryAdd(type, true);
79+
return true;
80+
}
81+
82+
if (type.FullName == "Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector")
83+
{
84+
KnownTypes.TryAdd(type, true);
85+
return true;
86+
}
7487
#endif
7588

7689
// classes are always unsafe (we should copy it fully to count references)

DeepCloner/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
// by using the '*' as shown below:
3333

3434
[assembly: AssemblyVersion("0.10.0.0")] // change this value only when api is changing
35-
[assembly: AssemblyFileVersion("0.11.0.0")]
36-
[assembly: AssemblyInformationalVersion("0.11.0.0")]
35+
[assembly: AssemblyFileVersion("0.10.1.0")]
36+
[assembly: AssemblyInformationalVersion("0.10.1.0")]
3737

3838
#if !DEBUG
3939
[assembly: AssemblyKeyFileAttribute("..\\public.snk")]

DeepCloner/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "0.11.0-*",
2+
"version": "0.10.1-*",
33
"buildOptions": {
44
"debugType": "portable",
55
"optimize": true,

0 commit comments

Comments
 (0)