From 11d056ee8420728eaab67c22ad9208356805c425 Mon Sep 17 00:00:00 2001 From: Matthew Davies Date: Thu, 6 Feb 2020 16:05:19 +0000 Subject: [PATCH] Added code missing from repo but present on NuGet These changes were decompiled using dotpeek. Chances are these changes were made on Jake's machine directly, then published direct to NuGet, but the code was never pushed to GitHub. If ever SqlObjectHydrator needs to change again, the changes should be based on this branch --- .gitignore | 1 + ObjectHydrator/Caching/CacheManager.cs | 47 ++- ObjectHydrator/Caching/MappingCache.cs | 24 +- .../ClassMapping/ClassMapGenerator.cs | 37 +- ObjectHydrator/ClassMapping/ClassMapResult.cs | 7 +- ObjectHydrator/ClassMapping/Mapping.cs | 82 ++--- .../ClassMapping/PropertyExtensionMethods.cs | 2 +- ObjectHydrator/ClassMapping/PropertyMap.cs | 18 +- .../ClassMapping/PropertyMapType.cs | 6 +- ObjectHydrator/ClassMapping/TableJoin.cs | 12 + ObjectHydrator/ClassMapping/TableJoinMap.cs | 15 + .../Configuration/DictionaryTableJoin.cs | 62 +--- .../Configuration/DictionaryTableJoin`1.cs | 53 +++ .../DynamicToDictionaryGenerator.cs | 9 +- .../Configuration/IDictionaryChildTable.cs | 7 + .../IDictionaryDestinationProperty.cs | 11 + .../Configuration/IDictionaryJoinCondition.cs | 9 + .../Configuration/IDictionaryKeyColumn.cs | 7 + .../Configuration/IDictionaryValueColumn.cs | 7 + ObjectHydrator/Configuration/IMapping.cs | 47 +-- ObjectHydrator/Configuration/ITableJoin.cs | 7 + ObjectHydrator/Configuration/ITableJoinMap.cs | 8 +- ObjectHydrator/FuncMappingsGenerator.cs | 39 ++ .../ILEmitting/DataReaderEmitter.cs | 55 +-- .../ILEmitting/ExpandoObjectInteractor.cs | 10 +- ObjectHydrator/ILEmitting/MappingEnum.cs | 6 +- ObjectHydrator/ILEmitting/MappingGenerator.cs | 334 ++++++++---------- .../ILEmitting/ObjectSettingEmitter.cs | 271 +++++++------- ObjectHydrator/ObjectHydrator.cs | 59 +--- ObjectHydrator/SqlObjectHydrator.csproj | 48 +-- 30 files changed, 661 insertions(+), 639 deletions(-) create mode 100644 ObjectHydrator/ClassMapping/TableJoin.cs create mode 100644 ObjectHydrator/ClassMapping/TableJoinMap.cs create mode 100644 ObjectHydrator/Configuration/DictionaryTableJoin`1.cs create mode 100644 ObjectHydrator/Configuration/IDictionaryChildTable.cs create mode 100644 ObjectHydrator/Configuration/IDictionaryDestinationProperty.cs create mode 100644 ObjectHydrator/Configuration/IDictionaryJoinCondition.cs create mode 100644 ObjectHydrator/Configuration/IDictionaryKeyColumn.cs create mode 100644 ObjectHydrator/Configuration/IDictionaryValueColumn.cs create mode 100644 ObjectHydrator/Configuration/ITableJoin.cs create mode 100644 ObjectHydrator/FuncMappingsGenerator.cs diff --git a/.gitignore b/.gitignore index d24693d..20ca22b 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,4 @@ _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML *.ide +.vs diff --git a/ObjectHydrator/Caching/CacheManager.cs b/ObjectHydrator/Caching/CacheManager.cs index d50abbf..02f106a 100644 --- a/ObjectHydrator/Caching/CacheManager.cs +++ b/ObjectHydrator/Caching/CacheManager.cs @@ -7,48 +7,43 @@ namespace SqlObjectHydrator.Caching { internal static class CacheManager { - internal static readonly Dictionary MappingCaches; + internal static readonly Dictionary MappingCaches = new Dictionary(); - static CacheManager() + public static void StoreMappingCache( + Func> mappingCache, + IDataReader dataReader, + Type configurationType ) { - MappingCaches = new Dictionary(); - } - - public static void StoreMappingCache( Func> mappingCache, IDataReader dataReader, Type configurationType ) - { - var cacheHashCode = GetCacheHashCode( dataReader, configurationType ); - MappingCaches.Add( cacheHashCode, mappingCache() ); + int cacheHashCode = CacheManager.GetCacheHashCode( dataReader, configurationType ); + CacheManager.MappingCaches.Add( cacheHashCode, (object)mappingCache() ); } public static int GetCacheHashCode( IDataReader dataReader, Type configurationType ) { - var result = typeof( T ).GetHashCode() + GetReaderHashCode( dataReader ); - if ( configurationType != null ) - { - result += configurationType.GetHashCode(); - } - return result; + int num = typeof( T ).GetHashCode() + CacheManager.GetReaderHashCode( dataReader ); + if ( configurationType != (Type)null ) + num += configurationType.GetHashCode(); + return num; } public static bool ContainsMappingCache( IDataReader dataReader, Type configurationType ) { - return MappingCaches.ContainsKey( GetCacheHashCode( dataReader, configurationType ) ); + return CacheManager.MappingCaches.ContainsKey( CacheManager.GetCacheHashCode( dataReader, configurationType ) ); } - public static MappingCache GetMappingCache( IDataReader dataReader, Type configurationType ) + public static MappingCache GetMappingCache( + IDataReader dataReader, + Type configurationType ) { - return (MappingCache)MappingCaches.FirstOrDefault( x => x.Key == GetCacheHashCode( dataReader, configurationType ) ).Value; + return (MappingCache)CacheManager.MappingCaches.FirstOrDefault>( (Func, bool>)( x => x.Key == CacheManager.GetCacheHashCode( dataReader, configurationType ) ) ).Value; } public static int GetReaderHashCode( IDataReader dataReader ) { - var hashcode = 0; - for ( var i = 0; i < dataReader.FieldCount; i++ ) - { - hashcode += dataReader.GetFieldType( i ).GetHashCode(); - hashcode += dataReader.GetName( i ).GetHashCode(); - } - return hashcode; + int num = 0; + for ( int i = 0; i < dataReader.FieldCount; ++i ) + num = num + dataReader.GetFieldType( i ).GetHashCode() + dataReader.GetName( i ).GetHashCode(); + return num; } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/Caching/MappingCache.cs b/ObjectHydrator/Caching/MappingCache.cs index e6112a2..a1d6af2 100644 --- a/ObjectHydrator/Caching/MappingCache.cs +++ b/ObjectHydrator/Caching/MappingCache.cs @@ -1,26 +1,30 @@ +using SqlObjectHydrator.ILEmitting; using System; using System.Collections.Generic; using System.Data; -using SqlObjectHydrator.ILEmitting; namespace SqlObjectHydrator.Caching { internal class MappingCache { - public MappingCache( Func, Dictionary, Func, object>>, T> func, Dictionary mappings ) + public MappingCache( + System.Func, Dictionary, System.Func, object>>, T> func, + Dictionary mappings ) { - Func = func; - Mappings = mappings; - TypeMaps = new Dictionary, Func, object>>(); + this.Func = func; + this.Mappings = mappings; + this.TypeMaps = new Dictionary, System.Func, object>>(); } - private Func, Dictionary, Func, object>>, T> Func { get; set; } + private System.Func, Dictionary, System.Func, object>>, T> Func { get; set; } + private Dictionary Mappings { get; set; } - private Dictionary, Func, object>> TypeMaps { get; set; } - public T Run( IDataReader dataReader ) + private Dictionary, System.Func, object>> TypeMaps { get; set; } + + public T Run( IDataReader dataReader ) { - return Func( dataReader, Mappings, TypeMaps ); + return this.Func( dataReader, this.Mappings, this.TypeMaps ); } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ClassMapping/ClassMapGenerator.cs b/ObjectHydrator/ClassMapping/ClassMapGenerator.cs index 647a286..bc9198d 100644 --- a/ObjectHydrator/ClassMapping/ClassMapGenerator.cs +++ b/ObjectHydrator/ClassMapping/ClassMapGenerator.cs @@ -1,35 +1,30 @@ -using System; +using SqlObjectHydrator.Configuration; +using System; using System.Collections.Generic; using System.Data; -using System.Dynamic; using System.Linq; -using SqlObjectHydrator.Configuration; namespace SqlObjectHydrator.ClassMapping { internal static class ClassMapGenerator { - public static ClassMapResult Generate( IDataReader dataReader, Type configurationType = null ) where T : new() + public static ClassMapResult Generate( + IDataReader dataReader, + Type configurationType = null ) + where T : new() { - var mappings = new Mapping(); - if ( configurationType != null ) + Mapping mapping = new Mapping(); + if ( configurationType != (Type)null ) + ( (IObjectHydratorConfiguration)Activator.CreateInstance( configurationType ) ).Mapping( (IMapping)mapping ); + ClassMapResult classMapResult = new ClassMapResult() { - var configuration = (IObjectHydratorConfiguration)Activator.CreateInstance( configurationType ); - configuration.Mapping( mappings ); - } - - var classMapResult = new ClassMapResult - { - Mappings = mappings + Mappings = mapping }; - - var baseType = ( typeof( T ).IsGenericType && typeof( T ).GetGenericTypeDefinition() == typeof( List<> ) ) ? typeof( T ).GetGenericArguments()[ 0 ] : typeof( T ); - if ( !mappings.TableMaps.ContainsValue( baseType ) ) - mappings.TableMaps.Add( 0, baseType ); - - mappings.TableMaps = mappings.TableMaps.OrderBy( x => x.Key ).ToDictionary( x => x.Key, x => x.Value ); - + Type type = !typeof( T ).IsGenericType || !( typeof( T ).GetGenericTypeDefinition() == typeof( List<> ) ) ? typeof( T ) : typeof( T ).GetGenericArguments()[ 0 ]; + if ( !mapping.TableMaps.ContainsValue( type ) ) + mapping.TableMaps.Add( 0, type ); + mapping.TableMaps = mapping.TableMaps.OrderBy, int>( (Func, int>)( x => x.Key ) ).ToDictionary, int, Type>( (Func, int>)( x => x.Key ), (Func, Type>)( x => x.Value ) ); return classMapResult; } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ClassMapping/ClassMapResult.cs b/ObjectHydrator/ClassMapping/ClassMapResult.cs index dbfdff8..d24c539 100644 --- a/ObjectHydrator/ClassMapping/ClassMapResult.cs +++ b/ObjectHydrator/ClassMapping/ClassMapResult.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; namespace SqlObjectHydrator.ClassMapping { @@ -6,10 +6,11 @@ internal class ClassMapResult { public ClassMapResult() { - TempDataStorage = new List>>(); + this.TempDataStorage = new List>>(); } public List>> TempDataStorage { get; private set; } + public Mapping Mappings { get; set; } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ClassMapping/Mapping.cs b/ObjectHydrator/ClassMapping/Mapping.cs index 0c77bd6..68388c9 100644 --- a/ObjectHydrator/ClassMapping/Mapping.cs +++ b/ObjectHydrator/ClassMapping/Mapping.cs @@ -1,3 +1,4 @@ +using SqlObjectHydrator.Configuration; using System; using System.Collections.Generic; using System.Data; @@ -5,101 +6,94 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; -using SqlObjectHydrator.Configuration; namespace SqlObjectHydrator.ClassMapping { internal class Mapping : IMapping { public Dictionary PropertyMaps { get; set; } + public Dictionary TableMaps { get; set; } + public List DictionaryTableJoins { get; set; } + public List TableJoins { get; set; } + public Dictionary, object> Joins { get; set; } + public Dictionary VariableTableTypes { get; set; } public Mapping() { - PropertyMaps = new Dictionary(); - TableMaps = new Dictionary(); - DictionaryTableJoins = new List(); - TableJoins = new List(); - Joins = new Dictionary, object>(); - VariableTableTypes = new Dictionary(); + this.PropertyMaps = new Dictionary(); + this.TableMaps = new Dictionary(); + this.DictionaryTableJoins = new List(); + this.TableJoins = new List(); + this.Joins = new Dictionary, object>(); + this.VariableTableTypes = new Dictionary(); } void IMapping.Table( int id ) { - TableMaps.Add( id, typeof( T ) ); + this.TableMaps.Add( id, typeof( T ) ); } - void IMapping.PropertyMap( Expression> property, Func setAction ) + void IMapping.PropertyMap( + Expression> property, + Func setAction ) { - PropertyMaps.Add( GetPropertyInfo( property.ToString().Split( '.' ).Last() ), new PropertyMap( setAction ) ); + this.PropertyMaps.Add( Mapping.GetPropertyInfo( ( (IEnumerable)property.ToString().Split( '.' ) ).Last() ), new PropertyMap( (Delegate)setAction ) ); } public void PropertyMap( Expression> property, string columnName ) { - PropertyMaps.Add( GetPropertyInfo( property.ToString().Split( '.' ).Last() ), new PropertyMap( columnName ) ); + this.PropertyMaps.Add( Mapping.GetPropertyInfo( ( (IEnumerable)property.ToString().Split( '.' ) ).Last() ), new PropertyMap( columnName ) ); } public void PropertyMap( Expression> property, int columnId ) { - PropertyMaps.Add( GetPropertyInfo( property.ToString().Split( '.' ).Last() ), new PropertyMap( columnId ) ); + this.PropertyMaps.Add( Mapping.GetPropertyInfo( ( (IEnumerable)property.ToString().Split( '.' ) ).Last() ), new PropertyMap( columnId ) ); } private static PropertyInfo GetPropertyInfo( string name ) { - var propertyInfo = typeof( T ).GetProperty( name ) ?? typeof( T ).GetProperty( name, BindingFlags.Instance | BindingFlags.NonPublic ); - return propertyInfo; + PropertyInfo property = typeof( T ).GetProperty( name ); + if ( (object)property == null ) + property = typeof( T ).GetProperty( name, BindingFlags.Instance | BindingFlags.NonPublic ); + return property; } - void IMapping.TableJoin( Func canJoin, Action> listSet ) + void IMapping.TableJoin( + Func canJoin, + Action> listSet ) { - TableJoins.Add( new TableJoinMap + this.TableJoins.Add( new TableJoinMap() { ChildType = typeof( TChild ), ParentType = typeof( TParent ), - CanJoin = canJoin, - ListSet = listSet + CanJoin = (object)canJoin, + ListSet = (object)listSet } ); } void IMapping.Join( Action> listSet ) { - Joins.Add( new KeyValuePair( typeof( TParent ), typeof( TChild ) ), listSet ); + this.Joins.Add( new KeyValuePair( typeof( TParent ), typeof( TChild ) ), (object)listSet ); } void IMapping.AddJoin( Func func ) { - var tableJoinMap = func( new TableJoin() ); - if ( tableJoinMap is DictionaryTableJoin ) - { - var dictionaryTableJoin = tableJoinMap as DictionaryTableJoin; - DictionaryTableJoins.Add( dictionaryTableJoin ); - TableMaps.Add( dictionaryTableJoin.ChildTable, typeof( ExpandoObject ) ); - } + ITableJoinMap tableJoinMap = func( (ITableJoin)new TableJoin() ); + if ( !( tableJoinMap is DictionaryTableJoin ) ) + return; + DictionaryTableJoin dictionaryTableJoin = tableJoinMap as DictionaryTableJoin; + this.DictionaryTableJoins.Add( dictionaryTableJoin ); + this.TableMaps.Add( dictionaryTableJoin.ChildTable, typeof( ExpandoObject ) ); } void IMapping.VariableTableType( Func action ) { - VariableTableTypes.Add( typeof( T ), action ); - } - } - - internal class TableJoinMap - { - public Type ParentType { get; set; } - public Type ChildType { get; set; } - public object CanJoin { get; set; } - public object ListSet { get; set; } - } - - internal class TableJoin : ITableJoin - { - public IDictionaryJoinCondition DictionaryTableJoin() where T : new() - { - return new DictionaryTableJoin(); + this.VariableTableTypes.Add( typeof( T ), (object)action ); } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ClassMapping/PropertyExtensionMethods.cs b/ObjectHydrator/ClassMapping/PropertyExtensionMethods.cs index 31de038..ee86713 100644 --- a/ObjectHydrator/ClassMapping/PropertyExtensionMethods.cs +++ b/ObjectHydrator/ClassMapping/PropertyExtensionMethods.cs @@ -19,4 +19,4 @@ public static Type GetActualPropertyType( this PropertyInfo propertyInfo ) return propertyInfo.PropertyType; } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ClassMapping/PropertyMap.cs b/ObjectHydrator/ClassMapping/PropertyMap.cs index 51ab7e1..578716b 100644 --- a/ObjectHydrator/ClassMapping/PropertyMap.cs +++ b/ObjectHydrator/ClassMapping/PropertyMap.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace SqlObjectHydrator.ClassMapping { @@ -7,25 +7,27 @@ internal class PropertyMap public PropertyMapType PropertyMapType { get; set; } public object SetAction { get; set; } + public int ColumnId { get; set; } + public string ColumnName { get; set; } public PropertyMap( Delegate setAction ) { - SetAction = setAction; - PropertyMapType = PropertyMapType.Func; + this.SetAction = (object)setAction; + this.PropertyMapType = PropertyMapType.Func; } public PropertyMap( int columnId ) { - ColumnId = columnId; - PropertyMapType = PropertyMapType.ColumnId; + this.ColumnId = columnId; + this.PropertyMapType = PropertyMapType.ColumnId; } public PropertyMap( string columnName ) { - ColumnName = columnName; - PropertyMapType = PropertyMapType.ColumnName; + this.ColumnName = columnName; + this.PropertyMapType = PropertyMapType.ColumnName; } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ClassMapping/PropertyMapType.cs b/ObjectHydrator/ClassMapping/PropertyMapType.cs index e099a5c..0f5d957 100644 --- a/ObjectHydrator/ClassMapping/PropertyMapType.cs +++ b/ObjectHydrator/ClassMapping/PropertyMapType.cs @@ -1,9 +1,9 @@ -namespace SqlObjectHydrator.ClassMapping +namespace SqlObjectHydrator.ClassMapping { internal enum PropertyMapType { Func, ColumnId, - ColumnName + ColumnName, } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ClassMapping/TableJoin.cs b/ObjectHydrator/ClassMapping/TableJoin.cs new file mode 100644 index 0000000..5ee1b40 --- /dev/null +++ b/ObjectHydrator/ClassMapping/TableJoin.cs @@ -0,0 +1,12 @@ +using SqlObjectHydrator.Configuration; + +namespace SqlObjectHydrator.ClassMapping +{ + internal class TableJoin : ITableJoin + { + public IDictionaryJoinCondition DictionaryTableJoin() where T : new() + { + return (IDictionaryJoinCondition)new DictionaryTableJoin(); + } + } +} diff --git a/ObjectHydrator/ClassMapping/TableJoinMap.cs b/ObjectHydrator/ClassMapping/TableJoinMap.cs new file mode 100644 index 0000000..bc39521 --- /dev/null +++ b/ObjectHydrator/ClassMapping/TableJoinMap.cs @@ -0,0 +1,15 @@ +using System; + +namespace SqlObjectHydrator.ClassMapping +{ + internal class TableJoinMap + { + public Type ParentType { get; set; } + + public Type ChildType { get; set; } + + public object CanJoin { get; set; } + + public object ListSet { get; set; } + } +} diff --git a/ObjectHydrator/Configuration/DictionaryTableJoin.cs b/ObjectHydrator/Configuration/DictionaryTableJoin.cs index d154472..202e439 100644 --- a/ObjectHydrator/Configuration/DictionaryTableJoin.cs +++ b/ObjectHydrator/Configuration/DictionaryTableJoin.cs @@ -1,67 +1,23 @@ -using System; -using System.Collections.Generic; +using System; namespace SqlObjectHydrator.Configuration { internal class DictionaryTableJoin : ITableJoinMap { public Type ParentTableType { get; set; } - public object Condition { get; set; } - public object Destination { get; set; } - public int ChildTable { get; set; } - public string KeyColumn { get; set; } - public Type KeyType { get; set; } - public string ValueColumn { get; set; } - public Type ValueType { get; set; } - } - internal class DictionaryTableJoin : IDictionaryJoinCondition, - IDictionaryKeyColumn, - IDictionaryValueColumn, - IDictionaryDestinationProperty, - IDictionaryChildTable where T : new() - { - private readonly DictionaryTableJoin _dictionaryTableJoin; + public object Condition { get; set; } - public DictionaryTableJoin() - { - _dictionaryTableJoin = new DictionaryTableJoin - { - ParentTableType = typeof(T) - }; - - } + public object Destination { get; set; } - public IDictionaryKeyColumn Condition( Func condition ) - { - _dictionaryTableJoin.Condition = condition; - return this; - } + public int ChildTable { get; set; } - public IDictionaryValueColumn KeyColumn( string keyColumn ) - { - _dictionaryTableJoin.KeyColumn = keyColumn; - return this; - } + public string KeyColumn { get; set; } - public IDictionaryDestinationProperty ValueColumn( string valueColumn ) - { - _dictionaryTableJoin.ValueColumn = valueColumn; - return this; - } + public Type KeyType { get; set; } - public IDictionaryChildTable SetDestinationProperty( Action> destination ) - { - _dictionaryTableJoin.Destination = destination; - _dictionaryTableJoin.KeyType = typeof( TKey ); - _dictionaryTableJoin.ValueType = typeof( TValue ); - return this; - } + public string ValueColumn { get; set; } - public ITableJoinMap ChildTable( int childTableId ) - { - _dictionaryTableJoin.ChildTable = childTableId; - return _dictionaryTableJoin; - } + public Type ValueType { get; set; } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/Configuration/DictionaryTableJoin`1.cs b/ObjectHydrator/Configuration/DictionaryTableJoin`1.cs new file mode 100644 index 0000000..d80fd29 --- /dev/null +++ b/ObjectHydrator/Configuration/DictionaryTableJoin`1.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; + +namespace SqlObjectHydrator.Configuration +{ + internal class DictionaryTableJoin : IDictionaryJoinCondition, IDictionaryKeyColumn, IDictionaryValueColumn, IDictionaryDestinationProperty, IDictionaryChildTable + where T : new() + { + private readonly DictionaryTableJoin _dictionaryTableJoin; + + public DictionaryTableJoin() + { + this._dictionaryTableJoin = new DictionaryTableJoin() + { + ParentTableType = typeof( T ) + }; + } + + public IDictionaryKeyColumn Condition( Func condition ) + { + this._dictionaryTableJoin.Condition = (object)condition; + return (IDictionaryKeyColumn)this; + } + + public IDictionaryValueColumn KeyColumn( string keyColumn ) + { + this._dictionaryTableJoin.KeyColumn = keyColumn; + return (IDictionaryValueColumn)this; + } + + public IDictionaryDestinationProperty ValueColumn( + string valueColumn ) + { + this._dictionaryTableJoin.ValueColumn = valueColumn; + return (IDictionaryDestinationProperty)this; + } + + public IDictionaryChildTable SetDestinationProperty( + Action> destination ) + { + this._dictionaryTableJoin.Destination = (object)destination; + this._dictionaryTableJoin.KeyType = typeof( TKey ); + this._dictionaryTableJoin.ValueType = typeof( TValue ); + return (IDictionaryChildTable)this; + } + + public ITableJoinMap ChildTable( int childTableId ) + { + this._dictionaryTableJoin.ChildTable = childTableId; + return (ITableJoinMap)this._dictionaryTableJoin; + } + } +} diff --git a/ObjectHydrator/Configuration/ExpressionGenerators/DynamicToDictionaryGenerator.cs b/ObjectHydrator/Configuration/ExpressionGenerators/DynamicToDictionaryGenerator.cs index 2a80c70..0dd3566 100644 --- a/ObjectHydrator/Configuration/ExpressionGenerators/DynamicToDictionaryGenerator.cs +++ b/ObjectHydrator/Configuration/ExpressionGenerators/DynamicToDictionaryGenerator.cs @@ -7,9 +7,12 @@ namespace SqlObjectHydrator.Configuration.ExpressionGenerators { internal static class DynamicToDictionaryGenerator { - public static Action> Generate( Action> setAction, string keyColumn, string valueColumn ) + public static Action> Generate( + Action> setAction, + string keyColumn, + string valueColumn ) { - return ( parent, list ) => setAction( parent, list.ToDictionary( x => (TKey)x.First( y => y.Key == keyColumn ).Value, x => (TValue)x.First( y => y.Key == valueColumn ).Value ) ); - } + return (Action>)( ( parent, list ) => setAction( parent, list.ToDictionary( (Func)( x => (TKey)x.First>( (Func, bool>)( y => y.Key == keyColumn ) ).Value ), (Func)( x => (TValue)x.First>( (Func, bool>)( y => y.Key == valueColumn ) ).Value ) ) ) ); + } } } diff --git a/ObjectHydrator/Configuration/IDictionaryChildTable.cs b/ObjectHydrator/Configuration/IDictionaryChildTable.cs new file mode 100644 index 0000000..9ec3f3f --- /dev/null +++ b/ObjectHydrator/Configuration/IDictionaryChildTable.cs @@ -0,0 +1,7 @@ +namespace SqlObjectHydrator.Configuration +{ + public interface IDictionaryChildTable + { + ITableJoinMap ChildTable( int childTableId ); + } +} diff --git a/ObjectHydrator/Configuration/IDictionaryDestinationProperty.cs b/ObjectHydrator/Configuration/IDictionaryDestinationProperty.cs new file mode 100644 index 0000000..e1f692b --- /dev/null +++ b/ObjectHydrator/Configuration/IDictionaryDestinationProperty.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace SqlObjectHydrator.Configuration +{ + public interface IDictionaryDestinationProperty where T : new() + { + IDictionaryChildTable SetDestinationProperty( + Action> destination ); + } +} diff --git a/ObjectHydrator/Configuration/IDictionaryJoinCondition.cs b/ObjectHydrator/Configuration/IDictionaryJoinCondition.cs new file mode 100644 index 0000000..b2dc7a8 --- /dev/null +++ b/ObjectHydrator/Configuration/IDictionaryJoinCondition.cs @@ -0,0 +1,9 @@ +using System; + +namespace SqlObjectHydrator.Configuration +{ + public interface IDictionaryJoinCondition where T : new() + { + IDictionaryKeyColumn Condition( Func condition ); + } +} diff --git a/ObjectHydrator/Configuration/IDictionaryKeyColumn.cs b/ObjectHydrator/Configuration/IDictionaryKeyColumn.cs new file mode 100644 index 0000000..20aa868 --- /dev/null +++ b/ObjectHydrator/Configuration/IDictionaryKeyColumn.cs @@ -0,0 +1,7 @@ +namespace SqlObjectHydrator.Configuration +{ + public interface IDictionaryKeyColumn where T : new() + { + IDictionaryValueColumn KeyColumn( string keyColumn ); + } +} diff --git a/ObjectHydrator/Configuration/IDictionaryValueColumn.cs b/ObjectHydrator/Configuration/IDictionaryValueColumn.cs new file mode 100644 index 0000000..55e8c08 --- /dev/null +++ b/ObjectHydrator/Configuration/IDictionaryValueColumn.cs @@ -0,0 +1,7 @@ +namespace SqlObjectHydrator.Configuration +{ + public interface IDictionaryValueColumn where T : new() + { + IDictionaryDestinationProperty ValueColumn( string valueColumn ); + } +} diff --git a/ObjectHydrator/Configuration/IMapping.cs b/ObjectHydrator/Configuration/IMapping.cs index eceeeac..3b3bdce 100644 --- a/ObjectHydrator/Configuration/IMapping.cs +++ b/ObjectHydrator/Configuration/IMapping.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Data; using System.Linq.Expressions; @@ -8,42 +8,23 @@ namespace SqlObjectHydrator.Configuration public interface IMapping { void Table( int id ); - void PropertyMap( Expression> property, Func setAction ); - void PropertyMap( Expression> property, string columnName ); - void PropertyMap( Expression> property, int columnId ); - void TableJoin( Func canJoin, Action> listSet ); - void Join( Action> listSet ); - void AddJoin( Func func ); - void VariableTableType( Func action ); - } - public interface ITableJoin - { - IDictionaryJoinCondition DictionaryTableJoin() where T : new(); - } + void PropertyMap( + Expression> property, + Func setAction ); - public interface IDictionaryJoinCondition where T : new() - { - IDictionaryKeyColumn Condition( Func condition ); - } + void PropertyMap( Expression> property, string columnName ); - public interface IDictionaryKeyColumn where T : new() - { - IDictionaryValueColumn KeyColumn( string keyColumn ); - } + void PropertyMap( Expression> property, int columnId ); - public interface IDictionaryValueColumn where T : new() - { - IDictionaryDestinationProperty ValueColumn( string valueColumn ); - } + void TableJoin( + Func canJoin, + Action> listSet ); - public interface IDictionaryDestinationProperty where T : new() - { - IDictionaryChildTable SetDestinationProperty( Action> destination ); - } + void Join( Action> listSet ); - public interface IDictionaryChildTable - { - ITableJoinMap ChildTable( int childTableId ); + void AddJoin( Func func ); + + void VariableTableType( Func action ); } -} \ No newline at end of file +} diff --git a/ObjectHydrator/Configuration/ITableJoin.cs b/ObjectHydrator/Configuration/ITableJoin.cs new file mode 100644 index 0000000..d4ef044 --- /dev/null +++ b/ObjectHydrator/Configuration/ITableJoin.cs @@ -0,0 +1,7 @@ +namespace SqlObjectHydrator.Configuration +{ + public interface ITableJoin + { + IDictionaryJoinCondition DictionaryTableJoin() where T : new(); + } +} diff --git a/ObjectHydrator/Configuration/ITableJoinMap.cs b/ObjectHydrator/Configuration/ITableJoinMap.cs index 23ecf61..c5505b1 100644 --- a/ObjectHydrator/Configuration/ITableJoinMap.cs +++ b/ObjectHydrator/Configuration/ITableJoinMap.cs @@ -1,4 +1,6 @@ -namespace SqlObjectHydrator.Configuration +namespace SqlObjectHydrator.Configuration { - public interface ITableJoinMap {} -} \ No newline at end of file + public interface ITableJoinMap + { + } +} diff --git a/ObjectHydrator/FuncMappingsGenerator.cs b/ObjectHydrator/FuncMappingsGenerator.cs new file mode 100644 index 0000000..fe7bef3 --- /dev/null +++ b/ObjectHydrator/FuncMappingsGenerator.cs @@ -0,0 +1,39 @@ +using SqlObjectHydrator.ClassMapping; +using SqlObjectHydrator.Configuration; +using SqlObjectHydrator.ILEmitting; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SqlObjectHydrator +{ + internal static class FuncMappingsGenerator + { + public static Dictionary Generate( Mapping mappings ) + { + return new Dictionary() + { + { + MappingEnum.DictionaryJoin, + (object) mappings.DictionaryTableJoins.Select>((Func>) (x => new KeyValuePair(x.Condition, x.Destination))).ToList>() + }, + { + MappingEnum.Join, + (object) mappings.Joins.Select, object>, object>((Func, object>, object>) (x => x.Value)).ToList() + }, + { + MappingEnum.TableJoin, + (object) mappings.TableJoins + }, + { + MappingEnum.PropertyMap, + (object) mappings.PropertyMaps + }, + { + MappingEnum.VariableTableType, + (object) mappings.VariableTableTypes + } + }; + } + } +} diff --git a/ObjectHydrator/ILEmitting/DataReaderEmitter.cs b/ObjectHydrator/ILEmitting/DataReaderEmitter.cs index 9d1a934..5acfdad 100644 --- a/ObjectHydrator/ILEmitting/DataReaderEmitter.cs +++ b/ObjectHydrator/ILEmitting/DataReaderEmitter.cs @@ -1,35 +1,38 @@ using System; +using System.Collections.Generic; using System.Data; using System.Linq; +using System.Reflection; using System.Reflection.Emit; namespace SqlObjectHydrator.ILEmitting { internal static class DataReaderEmitter { - public static void GetPropertyValue( ILGenerator emitter, Type type, int fieldId, bool nullable, object map = null ) + public static void GetPropertyValue( + ILGenerator emitter, + Type type, + int fieldId, + bool nullable, + object map = null ) { if ( nullable ) { - var tempValue = emitter.DeclareLocal( type ); - - emitter.Emit( OpCodes.Ldloca_S, tempValue ); + LocalBuilder local = emitter.DeclareLocal( type ); + emitter.Emit( OpCodes.Ldloca_S, local ); emitter.Emit( OpCodes.Initobj, type ); - - var ifNotNull = emitter.DefineLabel(); + Label label = emitter.DefineLabel(); emitter.Emit( OpCodes.Ldarg_0 ); emitter.Emit( OpCodes.Ldc_I4, fieldId ); - emitter.Emit( OpCodes.Callvirt, typeof( IDataRecord ).GetMethod("IsDBNull") ); - emitter.Emit( OpCodes.Brtrue, ifNotNull ); - + emitter.Emit( OpCodes.Callvirt, typeof( IDataRecord ).GetMethod( "IsDBNull" ) ); + emitter.Emit( OpCodes.Brtrue, label ); emitter.Emit( OpCodes.Ldarg_0 ); emitter.Emit( OpCodes.Ldc_I4, fieldId ); - emitter.Emit( OpCodes.Callvirt, typeof( IDataRecord ).GetMethod( GetDataReaderMethodName( type.GetGenericArguments()[ 0 ] ) ) ); - emitter.Emit( OpCodes.Newobj, type.GetConstructors().First( x => x.GetParameters().First().ParameterType == type.GetGenericArguments()[ 0 ] ) ); - emitter.Emit( OpCodes.Stloc, tempValue ); - emitter.MarkLabel( ifNotNull ); - - emitter.Emit( OpCodes.Ldloc, tempValue ); + emitter.Emit( OpCodes.Callvirt, typeof( IDataRecord ).GetMethod( DataReaderEmitter.GetDataReaderMethodName( type.GetGenericArguments()[ 0 ] ) ) ); + emitter.Emit( OpCodes.Newobj, ( (IEnumerable)type.GetConstructors() ).First( (Func)( x => ( (IEnumerable)x.GetParameters() ).First().ParameterType == type.GetGenericArguments()[ 0 ] ) ) ); + emitter.Emit( OpCodes.Stloc, local ); + emitter.MarkLabel( label ); + emitter.Emit( OpCodes.Ldloc, local ); } else { @@ -41,35 +44,33 @@ public static void GetPropertyValue( ILGenerator emitter, Type type, int fieldId emitter.Emit( OpCodes.Isinst, typeof( string ) ); } else - emitter.Emit( OpCodes.Callvirt, typeof( IDataRecord ).GetMethod( GetDataReaderMethodName( type ) ) ); + emitter.Emit( OpCodes.Callvirt, typeof( IDataRecord ).GetMethod( DataReaderEmitter.GetDataReaderMethodName( type ) ) ); } } private static string GetDataReaderMethodName( Type propertyType ) { - if ( propertyType == typeof( Boolean ) ) + if ( propertyType == typeof( bool ) ) return "GetBoolean"; - if ( propertyType == typeof( Byte ) ) + if ( propertyType == typeof( byte ) ) return "GetByte"; - if ( propertyType == typeof( Char ) ) + if ( propertyType == typeof( char ) ) return "GetChar"; if ( propertyType == typeof( DateTime ) ) return "GetDateTime"; if ( propertyType == typeof( Decimal ) ) return "GetDecimal"; - if ( propertyType == typeof( Double ) ) + if ( propertyType == typeof( double ) ) return "GetDouble"; - if ( propertyType == typeof( Single ) ) + if ( propertyType == typeof( float ) ) return "GetFloat"; if ( propertyType == typeof( Guid ) ) return "GetGuid"; - if ( propertyType == typeof( Int16 ) ) + if ( propertyType == typeof( short ) ) return "GetInt16"; - if ( propertyType == typeof( Int32 ) ) + if ( propertyType == typeof( int ) ) return "GetInt32"; - if ( propertyType == typeof( Int64 ) ) - return "GetInt64"; - return "GetString"; + return propertyType == typeof( long ) ? "GetInt64" : "GetString"; } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ILEmitting/ExpandoObjectInteractor.cs b/ObjectHydrator/ILEmitting/ExpandoObjectInteractor.cs index b86712f..79f3563 100644 --- a/ObjectHydrator/ILEmitting/ExpandoObjectInteractor.cs +++ b/ObjectHydrator/ILEmitting/ExpandoObjectInteractor.cs @@ -6,7 +6,11 @@ namespace SqlObjectHydrator.ILEmitting { internal static class ExpandoObjectInteractor { - public static void SetExpandoProperty( ILGenerator emiter, LocalBuilder expando, string propertyName, LocalBuilder value ) + public static void SetExpandoProperty( + ILGenerator emiter, + LocalBuilder expando, + string propertyName, + LocalBuilder value ) { emiter.Emit( OpCodes.Ldloc, expando ); emiter.Emit( OpCodes.Ldnull ); @@ -15,13 +19,11 @@ public static void SetExpandoProperty( ILGenerator emiter, LocalBuilder expando, if ( value.LocalType.IsValueType ) emiter.Emit( OpCodes.Box, value.LocalType ); else - { emiter.Emit( OpCodes.Castclass, typeof( object ) ); - } emiter.Emit( OpCodes.Ldstr, propertyName ); emiter.Emit( OpCodes.Ldc_I4_0 ); emiter.Emit( OpCodes.Ldc_I4_1 ); emiter.Emit( OpCodes.Call, typeof( ExpandoObject ).GetMethod( "TrySetValue", BindingFlags.Instance | BindingFlags.NonPublic ) ); } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ILEmitting/MappingEnum.cs b/ObjectHydrator/ILEmitting/MappingEnum.cs index ae48bae..c01a23a 100644 --- a/ObjectHydrator/ILEmitting/MappingEnum.cs +++ b/ObjectHydrator/ILEmitting/MappingEnum.cs @@ -1,4 +1,4 @@ -namespace SqlObjectHydrator.ILEmitting +namespace SqlObjectHydrator.ILEmitting { internal enum MappingEnum { @@ -6,6 +6,6 @@ internal enum MappingEnum Join, DictionaryJoin, PropertyMap, - VariableTableType + VariableTableType, } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ILEmitting/MappingGenerator.cs b/ObjectHydrator/ILEmitting/MappingGenerator.cs index fd88e1c..5c3b64c 100644 --- a/ObjectHydrator/ILEmitting/MappingGenerator.cs +++ b/ObjectHydrator/ILEmitting/MappingGenerator.cs @@ -1,12 +1,13 @@ -using System; +using SqlObjectHydrator.ClassMapping; +using SqlObjectHydrator.Configuration; +using SqlObjectHydrator.Configuration.ExpressionGenerators; +using System; using System.Collections.Generic; using System.Data; using System.Dynamic; using System.Linq; using System.Reflection; using System.Reflection.Emit; -using SqlObjectHydrator.ClassMapping; -using SqlObjectHydrator.Configuration.ExpressionGenerators; namespace SqlObjectHydrator.ILEmitting { @@ -17,226 +18,175 @@ public static void NextResult( IDataReader dataReader ) dataReader.NextResult(); } - public static Func, Dictionary, Func, object>>, T> Generate( IDataReader dataReader, ClassMapResult classMapResult ) where T : new() + public static Func, Dictionary, Func, object>>, T> Generate( + IDataReader dataReader, + ClassMapResult classMapResult ) + where T : new() { - var baseType = ( typeof( T ).IsGenericType && typeof( T ).GetGenericTypeDefinition() == typeof( List<> ) ) ? typeof( T ).GetGenericArguments()[ 0 ] : typeof( T ); - var isList = ( typeof( T ).IsGenericType && typeof( T ).GetGenericTypeDefinition() == typeof( List<> ) ); - - #region working dynamicmethod - - var method = new DynamicMethod( "", typeof( T ), new[] + Type baseType = !typeof( T ).IsGenericType || !( typeof( T ).GetGenericTypeDefinition() == typeof( List<> ) ) ? typeof( T ) : typeof( T ).GetGenericArguments()[ 0 ]; + bool flag = typeof( T ).IsGenericType && typeof( T ).GetGenericTypeDefinition() == typeof( List<> ); + DynamicMethod dynamicMethod = new DynamicMethod( "", typeof( T ), new Type[ 3 ] { - typeof( IDataReader ), - typeof( Dictionary ), - typeof( Dictionary, Func, object>> ) + typeof (IDataReader), + typeof (Dictionary), + typeof (Dictionary, Func, object>>) }, true ); - var emitter = method.GetILGenerator(); - - #endregion - - #region dynamicmethod that outputs dll - - //var assemblyName = new AssemblyName("SomeName"); - //var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave, @"d:\"); - //var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll"); - - //TypeBuilder builder = moduleBuilder.DefineType("Test", TypeAttributes.Public); - //var methodBuilder = builder.DefineMethod("DynamicCreate", MethodAttributes.Public, typeof(T), new[] { typeof( IDataReader ),typeof( Dictionary ),typeof( Dictionary, object>> ) }); - //var emitter = methodBuilder.GetILGenerator(); - - #endregion - - //Create Func Variables - var tableJoinsLocalBuilders = new Dictionary>(); - var joinLocalBuilders = new Dictionary, LocalBuilder>(); - var dictionaryTableJoinsLocalBuilders = new Dictionary, KeyValuePair>(); - - #region Populate Mapping Variables - + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + Dictionary> dictionary1 = new Dictionary>(); + Dictionary, LocalBuilder> dictionary2 = new Dictionary, LocalBuilder>(); + Dictionary, KeyValuePair> dictionary3 = new Dictionary, KeyValuePair>(); if ( classMapResult.Mappings.TableJoins.Count > 0 ) { - var tableJoins = classMapResult.Mappings.TableJoins.ToList(); - var tableJoinsLocal = emitter.DeclareLocal( typeof( List ) ); - emitter.Emit( OpCodes.Ldarg_1 ); - emitter.Emit( OpCodes.Ldc_I4, (int)MappingEnum.TableJoin ); - emitter.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetMethod( "GetValueOrDefault", BindingFlags.Instance | BindingFlags.NonPublic ) ); - emitter.Emit( OpCodes.Castclass, typeof( List ) ); - emitter.Emit( OpCodes.Stloc, tableJoinsLocal ); - - foreach ( var tableJoin in classMapResult.Mappings.TableJoins ) + List list = classMapResult.Mappings.TableJoins.ToList(); + LocalBuilder local1 = ilGenerator.DeclareLocal( typeof( List ) ); + ilGenerator.Emit( OpCodes.Ldarg_1 ); + ilGenerator.Emit( OpCodes.Ldc_I4, 0 ); + ilGenerator.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetMethod( "GetValueOrDefault", BindingFlags.Instance | BindingFlags.NonPublic ) ); + ilGenerator.Emit( OpCodes.Castclass, typeof( List ) ); + ilGenerator.Emit( OpCodes.Stloc, local1 ); + foreach ( TableJoinMap tableJoin in classMapResult.Mappings.TableJoins ) { - var canJoinLocal = emitter.DeclareLocal( tableJoin.CanJoin.GetType() ); - var listSetLocal = emitter.DeclareLocal( tableJoin.ListSet.GetType() ); - - var tempLocal = emitter.DeclareLocal( typeof( TableJoinMap ) ); - - var index = tableJoins.IndexOf( tableJoin ); - - emitter.Emit( OpCodes.Ldloc, tableJoinsLocal ); - emitter.Emit( OpCodes.Ldc_I4, index ); - emitter.Emit( OpCodes.Call, typeof( List ).GetProperty( "Item" ).GetGetMethod() ); - emitter.Emit( OpCodes.Stloc, tempLocal ); - emitter.Emit( OpCodes.Ldloc, tempLocal ); - emitter.Emit( OpCodes.Call, typeof( TableJoinMap ).GetProperty( "CanJoin" ).GetGetMethod() ); - emitter.Emit( OpCodes.Castclass, tableJoin.CanJoin.GetType() ); - emitter.Emit( OpCodes.Stloc, canJoinLocal ); - emitter.Emit( OpCodes.Ldloc, tempLocal ); - emitter.Emit( OpCodes.Call, typeof( TableJoinMap ).GetProperty( "ListSet" ).GetGetMethod() ); - emitter.Emit( OpCodes.Castclass, tableJoin.ListSet.GetType() ); - emitter.Emit( OpCodes.Stloc, listSetLocal ); - - tableJoinsLocalBuilders.Add( tableJoin, new KeyValuePair( canJoinLocal, listSetLocal ) ); + LocalBuilder localBuilder = ilGenerator.DeclareLocal( tableJoin.CanJoin.GetType() ); + LocalBuilder local2 = ilGenerator.DeclareLocal( tableJoin.ListSet.GetType() ); + LocalBuilder local3 = ilGenerator.DeclareLocal( typeof( TableJoinMap ) ); + int num = list.IndexOf( tableJoin ); + ilGenerator.Emit( OpCodes.Ldloc, local1 ); + ilGenerator.Emit( OpCodes.Ldc_I4, num ); + ilGenerator.Emit( OpCodes.Call, typeof( List ).GetProperty( "Item" ).GetGetMethod() ); + ilGenerator.Emit( OpCodes.Stloc, local3 ); + ilGenerator.Emit( OpCodes.Ldloc, local3 ); + ilGenerator.Emit( OpCodes.Call, typeof( TableJoinMap ).GetProperty( "CanJoin" ).GetGetMethod() ); + ilGenerator.Emit( OpCodes.Castclass, tableJoin.CanJoin.GetType() ); + ilGenerator.Emit( OpCodes.Stloc, localBuilder ); + ilGenerator.Emit( OpCodes.Ldloc, local3 ); + ilGenerator.Emit( OpCodes.Call, typeof( TableJoinMap ).GetProperty( "ListSet" ).GetGetMethod() ); + ilGenerator.Emit( OpCodes.Castclass, tableJoin.ListSet.GetType() ); + ilGenerator.Emit( OpCodes.Stloc, local2 ); + dictionary1.Add( tableJoin, new KeyValuePair( localBuilder, local2 ) ); } } - - if ( classMapResult.Mappings.Joins.Count > 0 ) { - var joins = classMapResult.Mappings.Joins.ToList(); - var joinsLocal = emitter.DeclareLocal( typeof( List ) ); - emitter.Emit( OpCodes.Ldarg_1 ); - emitter.Emit( OpCodes.Ldc_I4, (int)MappingEnum.Join ); - emitter.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetMethod( "GetValueOrDefault", BindingFlags.Instance | BindingFlags.NonPublic ) ); - emitter.Emit( OpCodes.Castclass, typeof( List ) ); - emitter.Emit( OpCodes.Stloc, joinsLocal ); - foreach ( var @join in joins ) + List, object>> list = classMapResult.Mappings.Joins.ToList, object>>(); + LocalBuilder local1 = ilGenerator.DeclareLocal( typeof( List ) ); + ilGenerator.Emit( OpCodes.Ldarg_1 ); + ilGenerator.Emit( OpCodes.Ldc_I4, 1 ); + ilGenerator.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetMethod( "GetValueOrDefault", BindingFlags.Instance | BindingFlags.NonPublic ) ); + ilGenerator.Emit( OpCodes.Castclass, typeof( List ) ); + ilGenerator.Emit( OpCodes.Stloc, local1 ); + foreach ( KeyValuePair, object> keyValuePair in list ) { - var local = emitter.DeclareLocal( @join.Value.GetType() ); - - var index = joins.IndexOf( @join ); - - emitter.Emit( OpCodes.Ldloc, joinsLocal ); - emitter.Emit( OpCodes.Ldc_I4, index ); - emitter.Emit( OpCodes.Call, typeof( List ).GetProperty( "Item" ).GetGetMethod() ); - emitter.Emit( OpCodes.Castclass, @join.Value.GetType() ); - emitter.Emit( OpCodes.Stloc, local ); - - joinLocalBuilders.Add( @join.Key, local ); + LocalBuilder local2 = ilGenerator.DeclareLocal( keyValuePair.Value.GetType() ); + int num = list.IndexOf( keyValuePair ); + ilGenerator.Emit( OpCodes.Ldloc, local1 ); + ilGenerator.Emit( OpCodes.Ldc_I4, num ); + ilGenerator.Emit( OpCodes.Call, typeof( List ).GetProperty( "Item" ).GetGetMethod() ); + ilGenerator.Emit( OpCodes.Castclass, keyValuePair.Value.GetType() ); + ilGenerator.Emit( OpCodes.Stloc, local2 ); + dictionary2.Add( keyValuePair.Key, local2 ); } } - if ( classMapResult.Mappings.DictionaryTableJoins.Count > 0 ) { - var tableJoinsLocal = emitter.DeclareLocal( typeof( List> ) ); - emitter.Emit( OpCodes.Ldarg_1 ); - emitter.Emit( OpCodes.Ldc_I4, (int)MappingEnum.DictionaryJoin ); - emitter.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetMethod( "GetValueOrDefault", BindingFlags.Instance | BindingFlags.NonPublic ) ); - emitter.Emit( OpCodes.Castclass, typeof( List> ) ); - emitter.Emit( OpCodes.Stloc, tableJoinsLocal ); - foreach ( var dictionaryTableJoin in classMapResult.Mappings.DictionaryTableJoins ) + LocalBuilder local1 = ilGenerator.DeclareLocal( typeof( List> ) ); + ilGenerator.Emit( OpCodes.Ldarg_1 ); + ilGenerator.Emit( OpCodes.Ldc_I4, 2 ); + ilGenerator.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetMethod( "GetValueOrDefault", BindingFlags.Instance | BindingFlags.NonPublic ) ); + ilGenerator.Emit( OpCodes.Castclass, typeof( List> ) ); + ilGenerator.Emit( OpCodes.Stloc, local1 ); + foreach ( DictionaryTableJoin dictionaryTableJoin in classMapResult.Mappings.DictionaryTableJoins ) { - var conditionLocal = emitter.DeclareLocal( dictionaryTableJoin.Condition.GetType() ); - var destinationLocal = emitter.DeclareLocal( typeof( Action<,> ).MakeGenericType( dictionaryTableJoin.ParentTableType, typeof( List ) ) ); - - var tempLocal = emitter.DeclareLocal( typeof( KeyValuePair ) ); - - var index = classMapResult.Mappings.DictionaryTableJoins.IndexOf( dictionaryTableJoin ); - emitter.Emit( OpCodes.Ldloc, tableJoinsLocal ); - emitter.Emit( OpCodes.Ldc_I4, index ); - emitter.Emit( OpCodes.Call, typeof( List> ).GetProperty( "Item" ).GetGetMethod() ); - emitter.Emit( OpCodes.Stloc, tempLocal ); - emitter.Emit( OpCodes.Ldloc, tempLocal ); - emitter.Emit( OpCodes.Ldfld, typeof( KeyValuePair ).GetField( "key", BindingFlags.Instance | BindingFlags.NonPublic ) ); - emitter.Emit( OpCodes.Castclass, dictionaryTableJoin.Condition.GetType() ); - emitter.Emit( OpCodes.Stloc, conditionLocal ); - emitter.Emit( OpCodes.Ldloc, tempLocal ); - emitter.Emit( OpCodes.Ldfld, typeof( KeyValuePair ).GetField( "value", BindingFlags.Instance | BindingFlags.NonPublic ) ); - emitter.Emit( OpCodes.Castclass, dictionaryTableJoin.Destination.GetType() ); - emitter.Emit( OpCodes.Ldstr, dictionaryTableJoin.KeyColumn ); - emitter.Emit( OpCodes.Ldstr, dictionaryTableJoin.ValueColumn ); - emitter.Emit( OpCodes.Call, typeof( DynamicToDictionaryGenerator ).GetMethod( "Generate" ).MakeGenericMethod( dictionaryTableJoin.ParentTableType, dictionaryTableJoin.KeyType, dictionaryTableJoin.ValueType ) ); - emitter.Emit( OpCodes.Stloc, destinationLocal ); - - dictionaryTableJoinsLocalBuilders.Add( new KeyValuePair( dictionaryTableJoin.ParentTableType, dictionaryTableJoin.ChildTable ), new KeyValuePair( conditionLocal, destinationLocal ) ); + LocalBuilder localBuilder = ilGenerator.DeclareLocal( dictionaryTableJoin.Condition.GetType() ); + LocalBuilder local2 = ilGenerator.DeclareLocal( typeof( Action<,> ).MakeGenericType( dictionaryTableJoin.ParentTableType, typeof( List ) ) ); + LocalBuilder local3 = ilGenerator.DeclareLocal( typeof( KeyValuePair ) ); + int num = classMapResult.Mappings.DictionaryTableJoins.IndexOf( dictionaryTableJoin ); + ilGenerator.Emit( OpCodes.Ldloc, local1 ); + ilGenerator.Emit( OpCodes.Ldc_I4, num ); + ilGenerator.Emit( OpCodes.Call, typeof( List> ).GetProperty( "Item" ).GetGetMethod() ); + ilGenerator.Emit( OpCodes.Stloc, local3 ); + ilGenerator.Emit( OpCodes.Ldloc, local3 ); + ilGenerator.Emit( OpCodes.Ldfld, typeof( KeyValuePair ).GetField( "key", BindingFlags.Instance | BindingFlags.NonPublic ) ); + ilGenerator.Emit( OpCodes.Castclass, dictionaryTableJoin.Condition.GetType() ); + ilGenerator.Emit( OpCodes.Stloc, localBuilder ); + ilGenerator.Emit( OpCodes.Ldloc, local3 ); + ilGenerator.Emit( OpCodes.Ldfld, typeof( KeyValuePair ).GetField( "value", BindingFlags.Instance | BindingFlags.NonPublic ) ); + ilGenerator.Emit( OpCodes.Castclass, dictionaryTableJoin.Destination.GetType() ); + ilGenerator.Emit( OpCodes.Ldstr, dictionaryTableJoin.KeyColumn ); + ilGenerator.Emit( OpCodes.Ldstr, dictionaryTableJoin.ValueColumn ); + ilGenerator.Emit( OpCodes.Call, typeof( DynamicToDictionaryGenerator ).GetMethod( nameof( Generate ) ).MakeGenericMethod( dictionaryTableJoin.ParentTableType, dictionaryTableJoin.KeyType, dictionaryTableJoin.ValueType ) ); + ilGenerator.Emit( OpCodes.Stloc, local2 ); + dictionary3.Add( new KeyValuePair( dictionaryTableJoin.ParentTableType, dictionaryTableJoin.ChildTable ), new KeyValuePair( localBuilder, local2 ) ); } } - - #endregion - - //Load Tables - var localBuilders = new Dictionary, LocalBuilder>(); - - var maxTableId = classMapResult.Mappings.TableMaps.Select( x=>x.Key ).OrderBy( x=>x).Last(); - for ( var i = 0; i <= maxTableId; i++ ) + Dictionary, LocalBuilder> source = new Dictionary, LocalBuilder>(); + int num1 = classMapResult.Mappings.TableMaps.Select, int>( (Func, int>)( x => x.Key ) ).OrderBy( (Func)( x => x ) ).Last(); + for ( int index = 0; index <= num1; ++index ) { - if ( ! classMapResult.Mappings.TableMaps.ContainsKey( i ) ) - continue; - - var type = classMapResult.Mappings.TableMaps[ i ]; - - var localBuilder = ObjectSettingEmitter.Emit( emitter, type, classMapResult.Mappings, i ); - localBuilders.Add( new KeyValuePair( type, i ), localBuilder ); - emitter.Emit( OpCodes.Ldarg_0 ); - emitter.Emit( OpCodes.Call, typeof( MappingGenerator ).GetMethod( "NextResult" ) ); + if ( classMapResult.Mappings.TableMaps.ContainsKey( index ) ) + { + Type tableMap = classMapResult.Mappings.TableMaps[ index ]; + LocalBuilder localBuilder = ObjectSettingEmitter.Emit( ilGenerator, tableMap, classMapResult.Mappings, index ); + source.Add( new KeyValuePair( tableMap, index ), localBuilder ); + ilGenerator.Emit( OpCodes.Ldarg_0 ); + ilGenerator.Emit( OpCodes.Call, typeof( MappingGenerator ).GetMethod( "NextResult" ) ); + } } - - #region Run Mappings - - foreach ( var tableJoinsLocalBuilder in tableJoinsLocalBuilders ) + foreach ( KeyValuePair> keyValuePair in dictionary1 ) { - var parentType = tableJoinsLocalBuilder.Key.ParentType; - var childType = tableJoinsLocalBuilder.Key.ChildType; - - emitter.Emit( OpCodes.Ldloc, localBuilders.First( x => x.Key.Key == parentType ).Value ); - emitter.Emit( OpCodes.Ldloc, localBuilders.First( x => x.Key.Key == childType ).Value ); - emitter.Emit( OpCodes.Ldloc, tableJoinsLocalBuilder.Value.Key ); - emitter.Emit( OpCodes.Ldloc, tableJoinsLocalBuilder.Value.Value ); - emitter.Emit( OpCodes.Call, typeof( MappingGenerator ).GetMethod( "JoinTables" ).MakeGenericMethod( parentType, childType ) ); + Type parentType = keyValuePair.Key.ParentType; + Type childType = keyValuePair.Key.ChildType; + ilGenerator.Emit( OpCodes.Ldloc, source.First, LocalBuilder>>( (Func, LocalBuilder>, bool>)( x => x.Key.Key == parentType ) ).Value ); + ilGenerator.Emit( OpCodes.Ldloc, source.First, LocalBuilder>>( (Func, LocalBuilder>, bool>)( x => x.Key.Key == childType ) ).Value ); + ilGenerator.Emit( OpCodes.Ldloc, keyValuePair.Value.Key ); + ilGenerator.Emit( OpCodes.Ldloc, keyValuePair.Value.Value ); + ilGenerator.Emit( OpCodes.Call, typeof( MappingGenerator ).GetMethod( "JoinTables" ).MakeGenericMethod( parentType, childType ) ); } - - foreach ( var joinLocalBuilder in joinLocalBuilders ) + foreach ( KeyValuePair, LocalBuilder> keyValuePair in dictionary2 ) { - var parentType = joinLocalBuilder.Key.Key; - var childType = joinLocalBuilder.Key.Value; - - emitter.Emit( OpCodes.Ldloc, localBuilders.First( x => x.Key.Key == parentType ).Value ); - emitter.Emit( OpCodes.Ldloc, localBuilders.First( x => x.Key.Key == childType ).Value ); - emitter.Emit( OpCodes.Ldloc, joinLocalBuilder.Value ); - emitter.Emit( OpCodes.Call, typeof( MappingGenerator ).GetMethod( "Join" ).MakeGenericMethod( parentType, childType ) ); + Type parentType = keyValuePair.Key.Key; + Type childType = keyValuePair.Key.Value; + ilGenerator.Emit( OpCodes.Ldloc, source.First, LocalBuilder>>( (Func, LocalBuilder>, bool>)( x => x.Key.Key == parentType ) ).Value ); + ilGenerator.Emit( OpCodes.Ldloc, source.First, LocalBuilder>>( (Func, LocalBuilder>, bool>)( x => x.Key.Key == childType ) ).Value ); + ilGenerator.Emit( OpCodes.Ldloc, keyValuePair.Value ); + ilGenerator.Emit( OpCodes.Call, typeof( MappingGenerator ).GetMethod( "Join" ).MakeGenericMethod( parentType, childType ) ); } - - foreach ( var dictionaryTableJoinsLocalBuilder in dictionaryTableJoinsLocalBuilders ) + foreach ( KeyValuePair, KeyValuePair> keyValuePair in dictionary3 ) { - var parentType = dictionaryTableJoinsLocalBuilder.Key.Key; - var childId = dictionaryTableJoinsLocalBuilder.Key.Value; - - emitter.Emit( OpCodes.Ldloc, localBuilders.First( x => x.Key.Key == parentType ).Value ); - emitter.Emit( OpCodes.Ldloc, localBuilders.First( x => x.Key.Value == childId ).Value ); - emitter.Emit( OpCodes.Ldloc, dictionaryTableJoinsLocalBuilder.Value.Key ); - emitter.Emit( OpCodes.Ldloc, dictionaryTableJoinsLocalBuilder.Value.Value ); - emitter.Emit( OpCodes.Call, typeof( MappingGenerator ).GetMethod( "JoinTables" ).MakeGenericMethod( parentType, typeof( ExpandoObject ) ) ); + Type parentType = keyValuePair.Key.Key; + int childId = keyValuePair.Key.Value; + ilGenerator.Emit( OpCodes.Ldloc, source.First, LocalBuilder>>( (Func, LocalBuilder>, bool>)( x => x.Key.Key == parentType ) ).Value ); + ilGenerator.Emit( OpCodes.Ldloc, source.First, LocalBuilder>>( (Func, LocalBuilder>, bool>)( x => x.Key.Value == childId ) ).Value ); + ilGenerator.Emit( OpCodes.Ldloc, keyValuePair.Value.Key ); + ilGenerator.Emit( OpCodes.Ldloc, keyValuePair.Value.Value ); + ilGenerator.Emit( OpCodes.Call, typeof( MappingGenerator ).GetMethod( "JoinTables" ).MakeGenericMethod( parentType, typeof( ExpandoObject ) ) ); } - - #endregion - - emitter.Emit( OpCodes.Ldloc, localBuilders.First( x => x.Key.Key == baseType ).Value ); - if ( !isList ) - emitter.Emit( OpCodes.Call, typeof( Enumerable ).GetMethods().First( x => x.Name == "FirstOrDefault" && x.GetParameters().Count() == 1 ).MakeGenericMethod( typeof( T ) ) ); - emitter.Emit( OpCodes.Ret ); - - #region dynamicmethod that outputs dll - - //var t = builder.CreateType(); - //assemblyBuilder.Save(assemblyName.Name + ".dll"); - //return null; - - #endregion - - #region working dynamicmethod - - return (Func, Dictionary, Func, object>>, T>)method.CreateDelegate( typeof( Func, Dictionary, Func, object>>, T> ) ); - - #endregion + ilGenerator.Emit( OpCodes.Ldloc, source.First, LocalBuilder>>( (Func, LocalBuilder>, bool>)( x => x.Key.Key == baseType ) ).Value ); + if ( !flag ) + ilGenerator.Emit( OpCodes.Call, ( (IEnumerable)typeof( Enumerable ).GetMethods() ).First( (Func)( x => + { + if ( x.Name == "FirstOrDefault" ) + return ( (IEnumerable)x.GetParameters() ).Count() == 1; + return false; + } ) ).MakeGenericMethod( typeof( T ) ) ); + ilGenerator.Emit( OpCodes.Ret ); + return (Func, Dictionary, Func, object>>, T>)dynamicMethod.CreateDelegate( typeof( Func, Dictionary, Func, object>>, T> ) ); } - public static void JoinTables( List parents, IEnumerable children, Func canJoin, Action> setFunc ) + public static void JoinTables( + List parents, + IEnumerable children, + Func canJoin, + Action> setFunc ) { - parents.ForEach( x => setFunc( x, children.Where( y => canJoin( x, y ) ).ToList() ) ); + parents.ForEach( (Action)( x => setFunc( x, children.Where( (Func)( y => canJoin( x, y ) ) ).ToList() ) ) ); } - public static void Join( List parents, List children, Action> setFunc ) + public static void Join( + List parents, + List children, + Action> setFunc ) { - parents.ForEach( x => setFunc( x, children ) ); + parents.ForEach( (Action)( x => setFunc( x, children ) ) ); } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ILEmitting/ObjectSettingEmitter.cs b/ObjectHydrator/ILEmitting/ObjectSettingEmitter.cs index bcbcdfc..9b6ef84 100644 --- a/ObjectHydrator/ILEmitting/ObjectSettingEmitter.cs +++ b/ObjectHydrator/ILEmitting/ObjectSettingEmitter.cs @@ -1,3 +1,4 @@ +using SqlObjectHydrator.ClassMapping; using System; using System.Collections.Generic; using System.Data; @@ -5,123 +6,110 @@ using System.Linq; using System.Reflection; using System.Reflection.Emit; -using SqlObjectHydrator.ClassMapping; namespace SqlObjectHydrator.ILEmitting { internal static class ObjectSettingEmitter { public static int TableId = 0; + private static object safeTypeMapsAddLockObj = new object(); - public static LocalBuilder Emit( ILGenerator emitter, Type type, Mapping mapping, int tableId ) + public static LocalBuilder Emit( + ILGenerator emitter, + Type type, + Mapping mapping, + int tableId ) { - var listType = typeof( List<> ).MakeGenericType( type ); - var resultLocalBuilder = emitter.DeclareLocal( listType ); - emitter.Emit( OpCodes.Newobj, listType.GetConstructors()[ 0 ] ); - emitter.Emit( OpCodes.Stloc, resultLocalBuilder ); - - var tempRoot = emitter.DeclareLocal( type ); - - LocalBuilder variableTableTypeFunc = null; - + Type localType = typeof( List<> ).MakeGenericType( type ); + LocalBuilder local1 = emitter.DeclareLocal( localType ); + emitter.Emit( OpCodes.Newobj, localType.GetConstructors()[ 0 ] ); + emitter.Emit( OpCodes.Stloc, local1 ); + LocalBuilder local2 = emitter.DeclareLocal( type ); + LocalBuilder local3 = (LocalBuilder)null; if ( mapping.VariableTableTypes.ContainsKey( type ) ) { - variableTableTypeFunc = emitter.DeclareLocal( typeof( Func ) ); - + local3 = emitter.DeclareLocal( typeof( Func ) ); emitter.Emit( OpCodes.Ldarg_1 ); - emitter.Emit( OpCodes.Ldc_I4, (int)MappingEnum.VariableTableType ); + emitter.Emit( OpCodes.Ldc_I4, 4 ); emitter.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetMethod( "GetValueOrDefault", BindingFlags.Instance | BindingFlags.NonPublic ) ); emitter.Emit( OpCodes.Castclass, typeof( Dictionary ) ); - - emitter.Emit( OpCodes.Ldtoken, type ); emitter.Emit( OpCodes.Call, typeof( Type ).GetMethod( "GetTypeFromHandle" ) ); emitter.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetProperty( "Item" ).GetGetMethod() ); emitter.Emit( OpCodes.Castclass, typeof( Func ) ); - emitter.Emit( OpCodes.Stloc, variableTableTypeFunc ); + emitter.Emit( OpCodes.Stloc, local3 ); } - - - //Define While Labels - var whileIf = emitter.DefineLabel(); - var whileStart = emitter.DefineLabel(); - - //Start While Loop - emitter.Emit( OpCodes.Br, whileIf ); - emitter.MarkLabel( whileStart ); - - //Create Root Variable + Label label1 = emitter.DefineLabel(); + Label label2 = emitter.DefineLabel(); + emitter.Emit( OpCodes.Br, label1 ); + emitter.MarkLabel( label2 ); emitter.Emit( OpCodes.Newobj, type.GetConstructors()[ 0 ] ); - emitter.Emit( OpCodes.Stloc, tempRoot ); - - //Get Type - var typeLocal = emitter.DeclareLocal( typeof( Type ) ); - + emitter.Emit( OpCodes.Stloc, local2 ); + LocalBuilder local4 = emitter.DeclareLocal( typeof( Type ) ); if ( mapping.VariableTableTypes.ContainsKey( type ) ) { - emitter.Emit( OpCodes.Ldloc, variableTableTypeFunc ); + emitter.Emit( OpCodes.Ldloc, local3 ); emitter.Emit( OpCodes.Ldarg_0 ); emitter.Emit( OpCodes.Callvirt, typeof( Func ).GetMethod( "Invoke" ) ); - emitter.Emit( OpCodes.Stloc, typeLocal ); + emitter.Emit( OpCodes.Stloc, local4 ); } else { emitter.Emit( OpCodes.Ldtoken, type ); emitter.Emit( OpCodes.Call, typeof( Type ).GetMethod( "GetTypeFromHandle" ) ); - emitter.Emit( OpCodes.Stloc, typeLocal ); + emitter.Emit( OpCodes.Stloc, local4 ); } - - - var endIf = emitter.DefineLabel(); - + Label label3 = emitter.DefineLabel(); emitter.Emit( OpCodes.Ldarg_2 ); - emitter.Emit( OpCodes.Ldc_I4, tableId); - emitter.Emit( OpCodes.Ldloc, typeLocal ); + emitter.Emit( OpCodes.Ldc_I4, tableId ); + emitter.Emit( OpCodes.Ldloc, local4 ); emitter.Emit( OpCodes.Call, typeof( ObjectSettingEmitter ).GetMethod( "GetMappingCacheTuple" ) ); emitter.Emit( OpCodes.Call, typeof( Dictionary, Func, object>> ).GetMethod( "ContainsKey" ) ); - emitter.Emit( OpCodes.Brtrue, endIf ); - - var objectMethodLocal = emitter.DeclareLocal( typeof( Func, object> ) ); - - emitter.Emit( OpCodes.Ldloc, typeLocal ); + emitter.Emit( OpCodes.Brtrue, label3 ); + LocalBuilder local5 = emitter.DeclareLocal( typeof( Func, object> ) ); + emitter.Emit( OpCodes.Ldloc, local4 ); emitter.Emit( OpCodes.Ldarg_0 ); emitter.Emit( OpCodes.Ldarg_1 ); emitter.Emit( OpCodes.Call, typeof( ObjectSettingEmitter ).GetMethod( "GenerateObjectBuilder" ) ); - emitter.Emit( OpCodes.Stloc, objectMethodLocal ); - + emitter.Emit( OpCodes.Stloc, local5 ); emitter.Emit( OpCodes.Ldarg_2 ); - emitter.Emit( OpCodes.Ldc_I4, tableId); - emitter.Emit( OpCodes.Ldloc, typeLocal ); + emitter.Emit( OpCodes.Ldc_I4, tableId ); + emitter.Emit( OpCodes.Ldloc, local4 ); emitter.Emit( OpCodes.Call, typeof( ObjectSettingEmitter ).GetMethod( "GetMappingCacheTuple" ) ); - emitter.Emit( OpCodes.Ldloc, objectMethodLocal ); - emitter.Emit( OpCodes.Call, typeof( Dictionary, Func, object>> ).GetMethod( "Add" ) ); - - emitter.MarkLabel( endIf ); - + emitter.Emit( OpCodes.Ldloc, local5 ); + emitter.Emit( OpCodes.Call, typeof( ObjectSettingEmitter ).GetMethod( "SafeTypeMapsAdd" ) ); + emitter.MarkLabel( label3 ); emitter.Emit( OpCodes.Ldarg_2 ); - emitter.Emit( OpCodes.Ldc_I4, tableId); - emitter.Emit( OpCodes.Ldloc, typeLocal ); + emitter.Emit( OpCodes.Ldc_I4, tableId ); + emitter.Emit( OpCodes.Ldloc, local4 ); emitter.Emit( OpCodes.Call, typeof( ObjectSettingEmitter ).GetMethod( "GetMappingCacheTuple" ) ); emitter.Emit( OpCodes.Call, typeof( Dictionary, Func, object>> ).GetProperty( "Item" ).GetGetMethod() ); emitter.Emit( OpCodes.Ldarg_0 ); emitter.Emit( OpCodes.Ldarg_1 ); emitter.Emit( OpCodes.Call, typeof( Func, object> ).GetMethod( "Invoke" ) ); emitter.Emit( OpCodes.Castclass, type ); - emitter.Emit( OpCodes.Stloc, tempRoot ); - - - //Add Root Variable To Result - emitter.Emit( OpCodes.Ldloc, resultLocalBuilder ); - emitter.Emit( OpCodes.Ldloc, tempRoot ); - emitter.Emit( OpCodes.Callvirt, listType.GetMethod( "Add" ) ); - - //While If - emitter.MarkLabel( whileIf ); + emitter.Emit( OpCodes.Stloc, local2 ); + emitter.Emit( OpCodes.Ldloc, local1 ); + emitter.Emit( OpCodes.Ldloc, local2 ); + emitter.Emit( OpCodes.Callvirt, localType.GetMethod( "Add" ) ); + emitter.MarkLabel( label1 ); emitter.Emit( OpCodes.Ldarg_0 ); emitter.Emit( OpCodes.Callvirt, typeof( IDataReader ).GetMethod( "Read" ) ); - emitter.Emit( OpCodes.Brtrue, whileStart ); //Continue While Loop + emitter.Emit( OpCodes.Brtrue, label2 ); + return local1; + } - return resultLocalBuilder; + public static void SafeTypeMapsAdd( + Dictionary, Func, object>> dictionary, + Tuple key, + Func, object> value ) + { + lock ( ObjectSettingEmitter.safeTypeMapsAddLockObj ) + { + if ( dictionary.ContainsKey( key ) ) + return; + dictionary.Add( key, value ); + } } public static Tuple GetMappingCacheTuple( int tableId, Type type ) @@ -129,96 +117,99 @@ public static Tuple GetMappingCacheTuple( int tableId, Type type ) return new Tuple( tableId, type ); } - public static Func, object> GenerateObjectBuilder( Type type, IDataRecord dataRecord, Dictionary mappings ) + public static Func, object> GenerateObjectBuilder( + Type type, + IDataRecord dataRecord, + Dictionary mappings ) { - var propertyMaps = mappings.ContainsKey( MappingEnum.PropertyMap ) ? mappings[ MappingEnum.PropertyMap ] as Dictionary : new Dictionary(); - var filteredPropertyMaps = propertyMaps.Where( x => x.Key.DeclaringType.IsAssignableFrom( type ) ).ToList(); - - var method = new DynamicMethod( "", typeof( object ), new[] + Dictionary source = mappings.ContainsKey( MappingEnum.PropertyMap ) ? mappings[ MappingEnum.PropertyMap ] as Dictionary : new Dictionary(); + List> list = source.Where>( (Func, bool>)( x => x.Key.DeclaringType.IsAssignableFrom( type ) ) ).ToList>(); + DynamicMethod dynamicMethod = new DynamicMethod( "", typeof( object ), new Type[ 2 ] { - typeof( IDataRecord ), - typeof( Dictionary ) + typeof (IDataRecord), + typeof (Dictionary) }, true ); - var emitter = method.GetILGenerator(); - - - var localPropertyMapsBuilders = new Dictionary(); - if ( filteredPropertyMaps.Count > 0 ) + ILGenerator ilGenerator1 = dynamicMethod.GetILGenerator(); + Dictionary dictionary = new Dictionary(); + if ( list.Count > 0 ) { - var propertyMapsLocal = emitter.DeclareLocal( typeof( List ) ); - - emitter.Emit( OpCodes.Ldarg_1 ); - emitter.Emit( OpCodes.Ldc_I4, (int)MappingEnum.PropertyMap ); - emitter.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetMethod( "GetValueOrDefault", BindingFlags.Instance | BindingFlags.NonPublic ) ); - emitter.Emit( OpCodes.Castclass, typeof( Dictionary ) ); - emitter.Emit( OpCodes.Call, typeof( Dictionary ).GetProperty( "Values" ).GetGetMethod() ); - emitter.Emit( OpCodes.Call, typeof( Enumerable ).GetMethod( "ToList" ).MakeGenericMethod( typeof( PropertyMap ) ) ); - emitter.Emit( OpCodes.Stloc, propertyMapsLocal ); - - foreach ( var propertyMap in filteredPropertyMaps.Where( x => x.Value.PropertyMapType == PropertyMapType.Func ) ) + LocalBuilder local1 = ilGenerator1.DeclareLocal( typeof( List ) ); + ilGenerator1.Emit( OpCodes.Ldarg_1 ); + ilGenerator1.Emit( OpCodes.Ldc_I4, 3 ); + ilGenerator1.Emit( OpCodes.Callvirt, typeof( Dictionary ).GetMethod( "GetValueOrDefault", BindingFlags.Instance | BindingFlags.NonPublic ) ); + ilGenerator1.Emit( OpCodes.Castclass, typeof( Dictionary ) ); + ilGenerator1.Emit( OpCodes.Call, typeof( Dictionary ).GetProperty( "Values" ).GetGetMethod() ); + ilGenerator1.Emit( OpCodes.Call, typeof( Enumerable ).GetMethod( "ToList" ).MakeGenericMethod( typeof( PropertyMap ) ) ); + ilGenerator1.Emit( OpCodes.Stloc, local1 ); + foreach ( KeyValuePair keyValuePair in list.Where>( (Func, bool>)( x => x.Value.PropertyMapType == PropertyMapType.Func ) ) ) { - var localBuilder = emitter.DeclareLocal( propertyMap.Value.SetAction.GetType() ); - var index = propertyMaps.Keys.ToList().IndexOf( propertyMap.Key ); - - emitter.Emit( OpCodes.Ldloc, propertyMapsLocal ); - emitter.Emit( OpCodes.Ldc_I4, index ); - emitter.Emit( OpCodes.Call, typeof( List ).GetProperty( "Item" ).GetGetMethod() ); - emitter.Emit( OpCodes.Call, typeof( PropertyMap ).GetProperty( "SetAction" ).GetGetMethod() ); - emitter.Emit( OpCodes.Castclass, propertyMap.Value.SetAction.GetType() ); - emitter.Emit( OpCodes.Stloc, localBuilder ); - localPropertyMapsBuilders.Add( propertyMap.Key, localBuilder ); + LocalBuilder local2 = ilGenerator1.DeclareLocal( keyValuePair.Value.SetAction.GetType() ); + int num = source.Keys.ToList().IndexOf( keyValuePair.Key ); + ilGenerator1.Emit( OpCodes.Ldloc, local1 ); + ilGenerator1.Emit( OpCodes.Ldc_I4, num ); + ilGenerator1.Emit( OpCodes.Call, typeof( List ).GetProperty( "Item" ).GetGetMethod() ); + ilGenerator1.Emit( OpCodes.Call, typeof( PropertyMap ).GetProperty( "SetAction" ).GetGetMethod() ); + ilGenerator1.Emit( OpCodes.Castclass, keyValuePair.Value.SetAction.GetType() ); + ilGenerator1.Emit( OpCodes.Stloc, local2 ); + dictionary.Add( keyValuePair.Key, local2 ); } } - - var objectVariable = emitter.DeclareLocal( type ); - - emitter.Emit( OpCodes.Newobj, type.GetConstructors()[ 0 ] ); - emitter.Emit( OpCodes.Stloc, objectVariable ); - - for ( var i = 0; i < dataRecord.FieldCount; i++ ) + LocalBuilder localBuilder = ilGenerator1.DeclareLocal( type ); + ilGenerator1.Emit( OpCodes.Newobj, type.GetConstructors()[ 0 ] ); + ilGenerator1.Emit( OpCodes.Stloc, localBuilder ); + for ( int i = 0; i < dataRecord.FieldCount; ++i ) { if ( type == typeof( ExpandoObject ) ) { - var valueLocalBuilder = emitter.DeclareLocal( dataRecord.GetFieldType( i ) ); - DataReaderEmitter.GetPropertyValue( emitter, dataRecord.GetFieldType( i ), i, false ); - emitter.Emit( OpCodes.Stloc, valueLocalBuilder ); - ExpandoObjectInteractor.SetExpandoProperty( emitter, objectVariable, dataRecord.GetName( i ), valueLocalBuilder ); + LocalBuilder local = ilGenerator1.DeclareLocal( dataRecord.GetFieldType( i ) ); + DataReaderEmitter.GetPropertyValue( ilGenerator1, dataRecord.GetFieldType( i ), i, false, (object)null ); + ilGenerator1.Emit( OpCodes.Stloc, local ); + ExpandoObjectInteractor.SetExpandoProperty( ilGenerator1, localBuilder, dataRecord.GetName( i ), local ); } else { PropertyInfo propertyInfo; - if ( filteredPropertyMaps.Any( x => x.Value.PropertyMapType == PropertyMapType.ColumnId && x.Value.ColumnId == i ) ) - propertyInfo = filteredPropertyMaps.First( x => x.Value.ColumnId == i ).Key; - else if ( filteredPropertyMaps.Any( x => x.Value.PropertyMapType == PropertyMapType.ColumnName && x.Value.ColumnName == dataRecord.GetName( i ) ) ) - propertyInfo = filteredPropertyMaps.First( x => x.Value.ColumnName == dataRecord.GetName( i ) ).Key; - else if ( filteredPropertyMaps.Any( x => x.Key.Name == dataRecord.GetName( i ) ) ) - propertyInfo = null; + if ( list.Any>( (Func, bool>)( x => + { + if ( x.Value.PropertyMapType == PropertyMapType.ColumnId ) + return x.Value.ColumnId == i; + return false; + } ) ) ) + propertyInfo = list.First>( (Func, bool>)( x => x.Value.ColumnId == i ) ).Key; + else if ( list.Any>( (Func, bool>)( x => + { + if ( x.Value.PropertyMapType == PropertyMapType.ColumnName ) + return x.Value.ColumnName == dataRecord.GetName( i ); + return false; + } ) ) ) + propertyInfo = list.First>( (Func, bool>)( x => x.Value.ColumnName == dataRecord.GetName( i ) ) ).Key; else - propertyInfo = type.GetProperty( dataRecord.GetName( i ) ); - if ( propertyInfo != null && propertyInfo.GetActualPropertyType() == dataRecord.GetFieldType( i ) && filteredPropertyMaps.Where( x => x.Value.PropertyMapType == PropertyMapType.Func ).All( x => x.Key != propertyInfo ) ) + propertyInfo = !list.Any>( (Func, bool>)( x => x.Key.Name == dataRecord.GetName( i ) ) ) ? type.GetProperty( dataRecord.GetName( i ) ) : (PropertyInfo)null; + if ( propertyInfo != (PropertyInfo)null && propertyInfo.GetActualPropertyType() == dataRecord.GetFieldType( i ) && list.Where>( (Func, bool>)( x => x.Value.PropertyMapType == PropertyMapType.Func ) ).All>( (Func, bool>)( x => x.Key != propertyInfo ) ) ) { - emitter.Emit( OpCodes.Ldloc, objectVariable ); - DataReaderEmitter.GetPropertyValue( emitter, propertyInfo.PropertyType, i, propertyInfo.IsNullable() ); - emitter.Emit( OpCodes.Callvirt, propertyInfo.GetSetMethod() ); + ilGenerator1.Emit( OpCodes.Ldloc, localBuilder ); + DataReaderEmitter.GetPropertyValue( ilGenerator1, propertyInfo.PropertyType, i, propertyInfo.IsNullable(), (object)null ); + ilGenerator1.Emit( OpCodes.Callvirt, propertyInfo.GetSetMethod() ); } } } - - foreach ( var propertyMap in filteredPropertyMaps.Where( x => x.Value.PropertyMapType == PropertyMapType.Func ) ) + foreach ( KeyValuePair keyValuePair in list.Where>( (Func, bool>)( x => x.Value.PropertyMapType == PropertyMapType.Func ) ) ) { - var propertyMapLocal = localPropertyMapsBuilders[ propertyMap.Key ]; - - emitter.Emit( OpCodes.Ldloc, objectVariable ); - emitter.Emit( OpCodes.Ldloc, propertyMapLocal ); - emitter.Emit( OpCodes.Ldarg_0 ); - emitter.Emit( OpCodes.Call, propertyMapLocal.LocalType.GetMethod( "Invoke" ) ); - emitter.Emit( OpCodes.Callvirt, propertyMap.Key.GetSetMethod() ?? propertyMap.Key.GetSetMethod( true ) ); + LocalBuilder local = dictionary[ keyValuePair.Key ]; + ilGenerator1.Emit( OpCodes.Ldloc, localBuilder ); + ilGenerator1.Emit( OpCodes.Ldloc, local ); + ilGenerator1.Emit( OpCodes.Ldarg_0 ); + ilGenerator1.Emit( OpCodes.Call, local.LocalType.GetMethod( "Invoke" ) ); + ILGenerator ilGenerator2 = ilGenerator1; + OpCode callvirt = OpCodes.Callvirt; + MethodInfo setMethod = keyValuePair.Key.GetSetMethod(); + if ( (object)setMethod == null ) + setMethod = keyValuePair.Key.GetSetMethod( true ); + ilGenerator2.Emit( callvirt, setMethod ); } - - emitter.Emit( OpCodes.Ldloc, objectVariable ); - emitter.Emit( OpCodes.Ret ); - - return (Func, object>)method.CreateDelegate( typeof( Func, object> ) ); + ilGenerator1.Emit( OpCodes.Ldloc, localBuilder ); + ilGenerator1.Emit( OpCodes.Ret ); + return (Func, object>)dynamicMethod.CreateDelegate( typeof( Func, object> ) ); } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/ObjectHydrator.cs b/ObjectHydrator/ObjectHydrator.cs index 107926f..1c92399 100644 --- a/ObjectHydrator/ObjectHydrator.cs +++ b/ObjectHydrator/ObjectHydrator.cs @@ -1,69 +1,46 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using SqlObjectHydrator.Caching; +using SqlObjectHydrator.Caching; using SqlObjectHydrator.ClassMapping; using SqlObjectHydrator.ILEmitting; +using System; +using System.Collections.Generic; +using System.Data; namespace SqlObjectHydrator { public static class ObjectHydrator { + private static object lockObj = new object(); + public static List DataReaderToList( this IDataReader dataReader, Type configuration = null ) where T : new() { - return Run>( dataReader, configuration ); + return ObjectHydrator.Run>( dataReader, configuration ); } - private static object lockObj = new object(); - private static T Run( IDataReader dataReader, Type configuration ) where T : new() { if ( !CacheManager.ContainsMappingCache( dataReader, configuration ) ) { - lock ( lockObj ) + lock ( ObjectHydrator.lockObj ) { if ( !CacheManager.ContainsMappingCache( dataReader, configuration ) ) { - var hashcode = CacheManager.GetReaderHashCode( dataReader ); - var classMapResult = new ClassMapResult(); - CacheManager.StoreMappingCache( () => GetMappingCache( dataReader, configuration, out classMapResult ), dataReader, configuration ); + CacheManager.GetReaderHashCode( dataReader ); + ClassMapResult classMapResult = new ClassMapResult(); + CacheManager.StoreMappingCache( (Func>)( () => ObjectHydrator.GetMappingCache( dataReader, configuration, out classMapResult ) ), dataReader, configuration ); } } } return CacheManager.GetMappingCache( dataReader, configuration ).Run( dataReader ); } - private static MappingCache GetMappingCache( IDataReader dataReader, Type configuration, out ClassMapResult classMapResult ) where T : new() + private static MappingCache GetMappingCache( + IDataReader dataReader, + Type configuration, + out ClassMapResult classMapResult ) + where T : new() { classMapResult = ClassMapGenerator.Generate( dataReader, configuration ); - var func = MappingGenerator.Generate( dataReader, classMapResult ); - return new MappingCache( func, FuncMappingsGenerator.Generate( classMapResult.Mappings ) ); - } - } - - internal static class FuncMappingsGenerator - { - public static Dictionary Generate( Mapping mappings ) - { - return new Dictionary - { - { - MappingEnum.DictionaryJoin, mappings.DictionaryTableJoins.Select( x => new KeyValuePair( x.Condition, x.Destination ) ).ToList() - }, - { - MappingEnum.Join, mappings.Joins.Select( x => x.Value ).ToList() - }, - { - MappingEnum.TableJoin, mappings.TableJoins - }, - { - MappingEnum.PropertyMap, mappings.PropertyMaps - }, - { - MappingEnum.VariableTableType, mappings.VariableTableTypes - } - }; + return new MappingCache( MappingGenerator.Generate( dataReader, classMapResult ), FuncMappingsGenerator.Generate( classMapResult.Mappings ) ); } } -} \ No newline at end of file +} diff --git a/ObjectHydrator/SqlObjectHydrator.csproj b/ObjectHydrator/SqlObjectHydrator.csproj index 0c8b723..484f9d4 100644 --- a/ObjectHydrator/SqlObjectHydrator.csproj +++ b/ObjectHydrator/SqlObjectHydrator.csproj @@ -1,19 +1,20 @@  - - + + Debug AnyCPU - {D47C95BD-9313-40DC-B0DC-B7C04A8E9E43} + {445867D9-CE1F-43EE-9AF0-ECE0D86713CF} Library - Properties - SqlObjectHydrator SqlObjectHydrator v4.0 - 512 + 2.3.5.0 + 512 + SqlObjectHydrator + AnyCPU true full false @@ -21,52 +22,51 @@ DEBUG;TRACE prompt 4 - false + AnyCPU pdbonly true bin\Release\ TRACE prompt 4 - false - - - - + + + + + - - - + + + + + + + + + + - - + - \ No newline at end of file