diff --git a/.vs/ObjectHydrator/v16/Server/sqlite3/db.lock b/.vs/ObjectHydrator/v16/Server/sqlite3/db.lock new file mode 100644 index 0000000..e69de29 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