#region Apache License 2.0
/*
Nuclex .NET Framework
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#endregion // Apache License 2.0
#if !NO_SETS
using System;
using System.Collections.Concurrent;
namespace Nuclex.Support.Cloning {
///
/// Cloning factory which uses expression trees to improve performance when cloning
/// is a high-frequency action.
///
public partial class ExpressionTreeCloner : ICloneFactory {
/// Initializes the static members of the expression tree cloner
static ExpressionTreeCloner() {
shallowFieldBasedCloners = new ConcurrentDictionary>();
deepFieldBasedCloners = new ConcurrentDictionary>();
shallowPropertyBasedCloners = new ConcurrentDictionary>();
deepPropertyBasedCloners = new ConcurrentDictionary>();
}
///
/// Creates a deep clone of the specified object, also creating clones of all
/// child objects being referenced
///
/// Type of the object that will be cloned
/// Object that will be cloned
/// A deep clone of the provided object
public static TCloned DeepFieldClone(TCloned objectToClone) {
object objectToCloneAsObject = objectToClone;
if(objectToCloneAsObject == null) {
return default(TCloned);
}
Func cloner = getOrCreateDeepFieldBasedCloner(typeof(TCloned));
return (TCloned)cloner(objectToCloneAsObject);
}
///
/// Creates a deep clone of the specified object, also creating clones of all
/// child objects being referenced
///
/// Type of the object that will be cloned
/// Object that will be cloned
/// A deep clone of the provided object
public static TCloned DeepPropertyClone(TCloned objectToClone) {
object objectToCloneAsObject = objectToClone;
if(objectToCloneAsObject == null) {
return default(TCloned);
}
Func cloner = getOrCreateDeepPropertyBasedCloner(typeof(TCloned));
return (TCloned)cloner(objectToCloneAsObject);
}
///
/// Creates a shallow clone of the specified object, reusing any referenced objects
///
/// Type of the object that will be cloned
/// Object that will be cloned
/// A shallow clone of the provided object
public static TCloned ShallowFieldClone(TCloned objectToClone) {
object objectToCloneAsObject = objectToClone;
if(objectToCloneAsObject == null) {
return default(TCloned);
}
Func cloner = getOrCreateShallowFieldBasedCloner(typeof(TCloned));
return (TCloned)cloner(objectToCloneAsObject);
}
///
/// Creates a shallow clone of the specified object, reusing any referenced objects
///
/// Type of the object that will be cloned
/// Object that will be cloned
/// A shallow clone of the provided object
public static TCloned ShallowPropertyClone(TCloned objectToClone) {
object objectToCloneAsObject = objectToClone;
if(objectToCloneAsObject == null) {
return default(TCloned);
}
Func cloner = getOrCreateShallowPropertyBasedCloner(typeof(TCloned));
return (TCloned)cloner(objectToCloneAsObject);
}
///
/// Creates a shallow clone of the specified object, reusing any referenced objects
///
/// Type of the object that will be cloned
/// Object that will be cloned
/// A shallow clone of the provided object
TCloned ICloneFactory.ShallowFieldClone(TCloned objectToClone) {
return ExpressionTreeCloner.ShallowFieldClone(objectToClone);
}
///
/// Creates a shallow clone of the specified object, reusing any referenced objects
///
/// Type of the object that will be cloned
/// Object that will be cloned
/// A shallow clone of the provided object
TCloned ICloneFactory.ShallowPropertyClone(TCloned objectToClone) {
return ExpressionTreeCloner.ShallowPropertyClone(objectToClone);
}
///
/// Creates a deep clone of the specified object, also creating clones of all
/// child objects being referenced
///
/// Type of the object that will be cloned
/// Object that will be cloned
/// A deep clone of the provided object
TCloned ICloneFactory.DeepFieldClone(TCloned objectToClone) {
return ExpressionTreeCloner.DeepFieldClone(objectToClone);
}
///
/// Creates a deep clone of the specified object, also creating clones of all
/// child objects being referenced
///
/// Type of the object that will be cloned
/// Object that will be cloned
/// A deep clone of the provided object
TCloned ICloneFactory.DeepPropertyClone(TCloned objectToClone) {
return ExpressionTreeCloner.DeepPropertyClone(objectToClone);
}
#if false
///
/// Transfers the state of one object into another, creating clones of referenced objects
///
/// Type of the object whose sate will be transferred
/// Original instance the state will be taken from
/// Target instance the state will be written to
/// Whether to perform a property-based state copy
public void DeepCopyState(TState original, TState target, bool propertyBased)
where TState : class {
throw new NotImplementedException();
}
///
/// Transfers the state of one object into another, creating clones of referenced objects
///
/// Type of the object whose sate will be transferred
/// Original instance the state will be taken from
/// Target instance the state will be written to
/// Whether to perform a property-based state copy
public void DeepCopyState(ref TState original, ref TState target, bool propertyBased)
where TState : struct {
throw new NotImplementedException();
}
/// Transfers the state of one object into another
/// Type of the object whose sate will be transferred
/// Original instance the state will be taken from
/// Target instance the state will be written to
/// Whether to perform a property-based state copy
public void ShallowCopyState(TState original, TState target, bool propertyBased)
where TState : class {
throw new NotImplementedException();
}
/// Transfers the state of one object into another
/// Type of the object whose sate will be transferred
/// Original instance the state will be taken from
/// Target instance the state will be written to
/// Whether to perform a property-based state copy
public void ShallowCopyState(ref TState original, ref TState target, bool propertyBased)
where TState : struct {
throw new NotImplementedException();
}
#endif
///
/// Retrieves the existing clone method for the specified type or compiles one if
/// none exists for the type yet
///
/// Type for which a clone method will be retrieved
/// The clone method for the specified type
private static Func getOrCreateShallowFieldBasedCloner(Type clonedType) {
Func cloner;
if(!shallowFieldBasedCloners.TryGetValue(clonedType, out cloner)) {
cloner = createShallowFieldBasedCloner(clonedType);
shallowFieldBasedCloners.TryAdd(clonedType, cloner);
}
return cloner;
}
///
/// Retrieves the existing clone method for the specified type or compiles one if
/// none exists for the type yet
///
/// Type for which a clone method will be retrieved
/// The clone method for the specified type
private static Func getOrCreateDeepFieldBasedCloner(Type clonedType) {
Func cloner;
if(!deepFieldBasedCloners.TryGetValue(clonedType, out cloner)) {
cloner = createDeepFieldBasedCloner(clonedType);
deepFieldBasedCloners.TryAdd(clonedType, cloner);
}
return cloner;
}
///
/// Retrieves the existing clone method for the specified type or compiles one if
/// none exists for the type yet
///
/// Type for which a clone method will be retrieved
/// The clone method for the specified type
private static Func getOrCreateShallowPropertyBasedCloner(Type clonedType) {
Func cloner;
if(!shallowPropertyBasedCloners.TryGetValue(clonedType, out cloner)) {
cloner = createShallowPropertyBasedCloner(clonedType);
shallowPropertyBasedCloners.TryAdd(clonedType, cloner);
}
return cloner;
}
///
/// Retrieves the existing clone method for the specified type or compiles one if
/// none exists for the type yet
///
/// Type for which a clone method will be retrieved
/// The clone method for the specified type
private static Func getOrCreateDeepPropertyBasedCloner(Type clonedType) {
Func cloner;
if(!deepPropertyBasedCloners.TryGetValue(clonedType, out cloner)) {
cloner = createDeepPropertyBasedCloner(clonedType);
deepPropertyBasedCloners.TryAdd(clonedType, cloner);
}
return cloner;
}
/// Compiled cloners that perform shallow clone operations
private static readonly ConcurrentDictionary<
Type, Func
> shallowFieldBasedCloners;
/// Compiled cloners that perform deep clone operations
private static readonly ConcurrentDictionary<
Type, Func
> deepFieldBasedCloners;
/// Compiled cloners that perform shallow clone operations
private static readonly ConcurrentDictionary<
Type, Func
> shallowPropertyBasedCloners;
/// Compiled cloners that perform deep clone operations
private static readonly ConcurrentDictionary<
Type, Func
> deepPropertyBasedCloners;
}
} // namespace Nuclex.Support.Cloning
#endif // !NO_SETS