Example #1
0
        protected internal ObjectPropertyValue[] GetObjectPropertyValues <T>(object[] primaryKeyValues)
        {
            if (primaryKeyValues == null)
            {
                throw new ArgumentNullException(nameof(primaryKeyValues));
            }

            if (primaryKeyValues.All(c => c == null))
            {
                return(null);
            }

            Func <object, ObjectPropertyValue[]> func;
            var objectTypeHandle = typeof(RawPrimaryKeysPlaceholderType <T>).TypeHandle;

            if (!this.propertyInfoAndValueGetterFuncByType.TryGetValue(objectTypeHandle, out func))
            {
                var typeDescriptor = this.TypeDescriptorProvider.GetTypeDescriptor(typeof(T));

                var parameter   = Expression.Parameter(typeof(object));
                var constructor = ConstructorInfoFastRef.ObjectPropertyValueConstructor;

                var index        = 0;
                var initializers = new List <Expression>();

                foreach (var property in typeDescriptor.PrimaryKeyProperties)
                {
                    Expression convertedValue;

                    var valueExpression = Expression.Convert(Expression.ArrayIndex(Expression.Convert(parameter, typeof(object[])), Expression.Constant(index)), typeof(object));
                    var propertyInfo    = DataAccessObjectTypeBuilder.GetPropertyInfo(this.GetConcreteTypeFromDefinitionType(typeDescriptor.Type), property.PropertyName);

                    if (property.PropertyType.IsDataAccessObjectType())
                    {
                        convertedValue = Expression.Convert(valueExpression, typeof(object));
                    }
                    else
                    {
                        convertedValue = Expression.Call(MethodInfoFastRef.ConvertChangeTypeMethod, valueExpression, Expression.Constant(propertyInfo.PropertyType));
                    }

                    var newExpression = Expression.New(constructor, Expression.Constant(propertyInfo.PropertyType), Expression.Constant(property.PropertyName), Expression.Constant(property.PersistedName), Expression.Constant(property.PropertyName.GetHashCode()), convertedValue);

                    initializers.Add(newExpression);
                    index++;
                }

                var body = Expression.NewArrayInit(typeof(ObjectPropertyValue), initializers);

                var lambdaExpression = Expression.Lambda(typeof(Func <object, ObjectPropertyValue[]>), body, parameter);

                func = (Func <object, ObjectPropertyValue[]>)lambdaExpression.Compile();

                var newPropertyInfoAndValueGetterFuncByType = this.propertyInfoAndValueGetterFuncByType.Clone(objectTypeHandle, func);

                this.propertyInfoAndValueGetterFuncByType = newPropertyInfoAndValueGetterFuncByType;
            }

            return(func(primaryKeyValues));
        }
Example #2
0
        private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration)
        {
            DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder;

            var hash               = configuration.GetSha1();
            var assemblyName       = new AssemblyName(typeDescriptorProvider.DataAccessModelType.Assembly.GetName().Name + "." + typeDescriptorProvider.DataAccessModelType.Name);
            var sharedAssemblyName = new AssemblyName("Shaolinq.GeneratedDataAccessModel");
            var assemblyBuilder    = AppDomain.CurrentDomain.DefineDynamicAssembly(sharedAssemblyName, AssemblyBuilderAccess.RunAndSave);
            var moduleBuilder      = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + "." + hash + ".dll");

            var propertiesBuilder = moduleBuilder.DefineType("$$$DataAccessModelProperties", TypeAttributes.Class, typeof(object));

            var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder, propertiesBuilder);

            var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder);

            dataAccessModelTypeBuilder.BuildTypePhase1(typeDescriptorProvider.DataAccessModelType);

            var typeDescriptors = typeDescriptorProvider.GetTypeDescriptors();

            foreach (var typeDescriptor in typeDescriptors)
            {
                dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type);
                dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1));
            }

            foreach (var typeDescriptor in typeDescriptors)
            {
                dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type];
                dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2));
            }

            assemblyBuildContext.DataAccessModelPropertiesTypeBuilder.CreateType();
            dataAccessModelTypeBuilder.BuildTypePhase2();

            bool saveConcreteAssembly;

            bool.TryParse(ConfigurationManager.AppSettings["Shaolinq.SaveConcreteAssembly"], out saveConcreteAssembly);

#if DEBUG
            const bool isInDebugMode = true;
#else
            const bool isInDebugMode = false;
#endif

            // ReSharper disable once ConditionIsAlwaysTrueOrFalse
            if (saveConcreteAssembly || isInDebugMode)
            {
                ActionUtils.IgnoreExceptions(() => assemblyBuilder.Save(assemblyName + "." + hash + ".dll"));
            }

            return(assemblyBuilder);
        }
		private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration)
		{
			DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder;

			var hash = configuration.GetSha1();
			var assemblyName = new AssemblyName(typeDescriptorProvider.DataAccessModelType.Assembly.GetName().Name + "." + typeDescriptorProvider.DataAccessModelType.Name);
			var sharedAssemblyName = new AssemblyName("Shaolinq.GeneratedDataAccessModel");
			var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(sharedAssemblyName, AssemblyBuilderAccess.RunAndSave);
			var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + "." + hash + ".dll");

			var propertiesBuilder = moduleBuilder.DefineType("$$$DataAccessModelProperties", TypeAttributes.Class, typeof(object));
			
			var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder, propertiesBuilder);

			var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder);
			dataAccessModelTypeBuilder.BuildTypePhase1(typeDescriptorProvider.DataAccessModelType);

			var typeDescriptors = typeDescriptorProvider.GetTypeDescriptors();
			
			foreach (var typeDescriptor in typeDescriptors)
			{
				dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type);
				dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1));
			}

			foreach (var typeDescriptor in typeDescriptors)
			{
				dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type];
				dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2));
			}

			assemblyBuildContext.DataAccessModelPropertiesTypeBuilder.CreateType();
			dataAccessModelTypeBuilder.BuildTypePhase2();

			bool saveConcreteAssembly;
			bool.TryParse(ConfigurationManager.AppSettings["Shaolinq.SaveConcreteAssembly"], out saveConcreteAssembly);

#if DEBUG
			const bool isInDebugMode = true;
#else
			const bool isInDebugMode = false;
#endif

			// ReSharper disable once ConditionIsAlwaysTrueOrFalse
			if (saveConcreteAssembly || isInDebugMode)
			{
				ActionUtils.IgnoreExceptions(() => assemblyBuilder.Save(assemblyName + "." + hash + ".dll"));
			}

			return assemblyBuilder;
		}
        private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration)
        {
            DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder;

            var configMd5       = configuration.GetMd5();
            var assemblyName    = new AssemblyName(typeDescriptorProvider.DataAccessModelType.Assembly.GetName().Name + "." + typeDescriptorProvider.DataAccessModelType.Name);
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
            var moduleBuilder   = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + "." + configMd5 + ".dll");

            var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder);

            var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder);

            dataAccessModelTypeBuilder.BuildType(typeDescriptorProvider.DataAccessModelType);

            var typeDescriptors = typeDescriptorProvider.GetTypeDescriptors();

            foreach (var typeDescriptor in typeDescriptors)
            {
                dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type);
                dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1));
            }

            foreach (var typeDescriptor in typeDescriptors)
            {
                dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type];
                dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2));
            }

            bool saveConcreteAssembly;

            bool.TryParse(ConfigurationManager.AppSettings["Shaolinq.SaveConcreteAssembly"], out saveConcreteAssembly);

#if DEBUG
            const bool isInDebugMode = true;
#else
            const bool isInDebugMode = false;
#endif

            if (saveConcreteAssembly || isInDebugMode)
            {
                ActionUtils.IgnoreExceptions(() => assemblyBuilder.Save(assemblyName + "." + configMd5 + ".dll"));
            }

            return(assemblyBuilder);
        }
        private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration)
        {
            DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder;

            var configMd5 = configuration.GetMd5();
            var assemblyName = new AssemblyName(typeDescriptorProvider.DataAccessModelType.Assembly.GetName().Name + "." + typeDescriptorProvider.DataAccessModelType.Name);
            var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
            var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + "." + configMd5 + ".dll");

            var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder);

            var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder);
            dataAccessModelTypeBuilder.BuildType(typeDescriptorProvider.DataAccessModelType);

            var typeDescriptors = typeDescriptorProvider.GetTypeDescriptors();

            foreach (var typeDescriptor in typeDescriptors)
            {
                dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type);
                dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1));
            }

            foreach (var typeDescriptor in typeDescriptors)
            {
                dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type];
                dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2));
            }

            bool saveConcreteAssembly;
            bool.TryParse(ConfigurationManager.AppSettings["Shaolinq.SaveConcreteAssembly"], out saveConcreteAssembly);

            #if DEBUG
            const bool isInDebugMode = true;
            #else
            const bool isInDebugMode = false;
            #endif

            if (saveConcreteAssembly || isInDebugMode)
            {
                ActionUtils.IgnoreExceptions(() => assemblyBuilder.Save(assemblyName + "." + configMd5 + ".dll"));
            }

            return assemblyBuilder;
        }
Example #6
0
        protected internal ObjectPropertyValue[] GetObjectPropertyValues <K>(Type type, K primaryKey, PrimaryKeyType primaryKeyType = PrimaryKeyType.Auto)
        {
            if (Equals(primaryKey, default(K)) && typeof(K).IsClass)
            {
                throw new ArgumentNullException(nameof(primaryKey));
            }

            var idType = primaryKey.GetType();
            var primaryKeyTypeHandle = Type.GetTypeHandle(primaryKey);
            Func <object, ObjectPropertyValue[]> func;

            if (!this.propertyInfoAndValueGetterFuncByType.TryGetValue(primaryKeyTypeHandle, out func))
            {
                var isSimpleKey      = false;
                var typeOfPrimaryKey = Type.GetTypeFromHandle(primaryKeyTypeHandle);
                var typeDescriptor   = this.TypeDescriptorProvider.GetTypeDescriptor(type);
                var idPropertyType   = typeDescriptor.PrimaryKeyProperties[0].PropertyType;

                if (primaryKeyType == PrimaryKeyType.Single || TypeDescriptor.IsSimpleType(idType) || (idPropertyType.IsAssignableFrom(idType) && primaryKeyType == PrimaryKeyType.Auto))
                {
                    isSimpleKey = true;
                }

                if (isSimpleKey && typeDescriptor.PrimaryKeyCount != 1)
                {
                    throw new InvalidOperationException("Composite primary key expected");
                }

                var parameter      = Expression.Parameter(typeof(object));
                var constructor    = ConstructorInfoFastRef.ObjectPropertyValueConstructor;
                var typedParameter = Expression.Convert(parameter, typeOfPrimaryKey);

                var initializers = new List <Expression>();
                var replacementPrimaryKeyValues = new Dictionary <string, Expression>();

                if (typeDescriptor.PrimaryKeyDerivableProperties.Count > 0)
                {
                    var properties = typeDescriptor
                                     .PrimaryKeyDerivableProperties
                                     .Where(c => idType.GetProperty(c.PropertyName, BindingFlags.Instance | BindingFlags.Public) != null)
                                     .ToList();

                    replacementPrimaryKeyValues = properties.ToDictionary
                                                  (
                        c => c.ComputedMemberAssignTarget.Name,
                        c => MemberAccessReplacer.Replace
                        (
                            c.ComputedMemberAssignmentValue, c.PropertyInfo,
                            Expression.Property(typedParameter, c.PropertyName)
                        )
                                                  );
                }

                foreach (var property in typeDescriptor.PrimaryKeyProperties)
                {
                    var isObjectType = property.PropertyType.IsDataAccessObjectType();

                    Expression valueExpression;

                    if (isSimpleKey)
                    {
                        valueExpression = parameter;
                    }
                    else
                    {
                        if (!replacementPrimaryKeyValues.TryGetValue(property.PropertyName, out valueExpression))
                        {
                            valueExpression = Expression.PropertyOrField(typedParameter, property.PropertyName);
                        }
                    }

                    Expression primaryKeyValue;

                    var propertyInfo = DataAccessObjectTypeBuilder.GetPropertyInfo(this.GetConcreteTypeFromDefinitionType(typeDescriptor.Type), property.PropertyName);

                    if (isObjectType)
                    {
                        var method = MethodInfoFastRef.DataAccessModelGetReferenceMethod.MakeGenericMethod(propertyInfo.PropertyType, valueExpression.Type);

                        if (isSimpleKey || valueExpression.Type.IsDataAccessObjectType())
                        {
                            primaryKeyValue = valueExpression;
                        }
                        else
                        {
                            primaryKeyValue = Expression.Call(Expression.Constant(this), method, valueExpression, Expression.Constant(PrimaryKeyType.Composite));
                        }
                    }
                    else
                    {
                        primaryKeyValue = Expression.Call(MethodInfoFastRef.ConvertChangeTypeMethod, Expression.Convert(valueExpression, typeof(object)), Expression.Constant(propertyInfo.PropertyType));
                    }

                    var newExpression = Expression.New
                                        (
                        constructor,
                        Expression.Constant(propertyInfo.PropertyType),
                        Expression.Constant(property.PropertyName),
                        Expression.Constant(property.PersistedName),
                        Expression.Constant(property.PropertyName.GetHashCode()),
                        Expression.Convert(primaryKeyValue, typeof(object))
                                        );

                    initializers.Add(newExpression);
                }

                var body = Expression.NewArrayInit(typeof(ObjectPropertyValue), initializers);

                var lambdaExpression = Expression.Lambda(typeof(Func <object, ObjectPropertyValue[]>), body, parameter);

                func = (Func <object, ObjectPropertyValue[]>)lambdaExpression.Compile();

                var newPropertyInfoAndValueGetterFuncByType = new Dictionary <RuntimeTypeHandle, Func <object, ObjectPropertyValue[]> >(this.propertyInfoAndValueGetterFuncByType)
                {
                    [primaryKeyTypeHandle] = func
                };

                this.propertyInfoAndValueGetterFuncByType = newPropertyInfoAndValueGetterFuncByType;
            }

            return(func(primaryKey));
        }
Example #7
0
        protected internal ObjectPropertyValue[] GetObjectPropertyValues <K>(Type type, K primaryKey, PrimaryKeyType primaryKeyType = PrimaryKeyType.Auto)
        {
            if (primaryKey == null)
            {
                throw new ArgumentNullException(nameof(primaryKey));
            }

            var key = new Pair <RuntimeTypeHandle, RuntimeTypeHandle>(type.TypeHandle, Type.GetTypeHandle(primaryKey));

            if (!this.objectPropertyValuesByAnonymousKeyFuncByType.TryGetValue(key, out var func))
            {
                var isSimpleKey      = false;
                var typeOfPrimaryKey = primaryKey.GetType();
                var typeDescriptor   = this.TypeDescriptorProvider.GetTypeDescriptor(type);
                var idPropertyType   = typeDescriptor.PrimaryKeyProperties[0].PropertyType;

                if (primaryKeyType == PrimaryKeyType.Single || TypeDescriptor.IsSimpleType(typeOfPrimaryKey) || (typeDescriptor.PrimaryKeyCount == 1 && idPropertyType.IsAssignableFrom(typeOfPrimaryKey) && primaryKeyType == PrimaryKeyType.Auto))
                {
                    isSimpleKey = true;
                }

                if (isSimpleKey && typeDescriptor.PrimaryKeyCount != 1)
                {
                    throw new InvalidOperationException($"Composite primary key expected for type {type} instead of key of type {typeOfPrimaryKey}");
                }

                var parameter      = Expression.Parameter(typeof(object));
                var constructor    = ConstructorInfoFastRef.ObjectPropertyValueConstructor;
                var typedParameter = Expression.Convert(parameter, typeOfPrimaryKey);

                var initializers = new List <Expression>();
                var replacementPrimaryKeyValues = new Dictionary <string, Expression>();

                if (typeDescriptor.PrimaryKeyDerivableProperties.Count > 0)
                {
                    var properties = typeDescriptor
                                     .PrimaryKeyDerivableProperties
                                     .Where(c => typeOfPrimaryKey.GetMostDerivedProperty(c.PropertyName) != null)
                                     .ToList();

                    replacementPrimaryKeyValues = properties.ToDictionary
                                                  (
                        c => c.ComputedMemberAssignTarget.Name,
                        c => SqlMemberAccessReplacer.Replace
                        (
                            c.ComputedMemberAssignmentValue,
                            c.PropertyInfo,
                            Expression.Convert(Expression.Property(typedParameter, typedParameter.Type.GetMostDerivedProperty(c.PropertyName)), c.PropertyInfo.PropertyType)
                        )
                                                  );
                }

                foreach (var property in typeDescriptor.PrimaryKeyProperties)
                {
                    var isObjectType = property.PropertyType.IsDataAccessObjectType();

                    Expression valueExpression;

                    if (isSimpleKey)
                    {
                        valueExpression = parameter;
                    }
                    else
                    {
                        if (!replacementPrimaryKeyValues.TryGetValue(property.PropertyName, out valueExpression))
                        {
                            valueExpression = Expression.Property(typedParameter, typedParameter.Type.GetMostDerivedProperty(property.PropertyName));
                        }
                    }

                    Expression primaryKeyValue;

                    var propertyInfo = DataAccessObjectTypeBuilder.GetPropertyInfo(GetConcreteTypeFromDefinitionType(typeDescriptor.Type), property.PropertyName);

                    if (isObjectType)
                    {
                        var method = MethodInfoFastRef.DataAccessModelGetReferenceMethod.MakeGenericMethod(propertyInfo.PropertyType, valueExpression.Type);

                        if (isSimpleKey || valueExpression.Type.IsDataAccessObjectType())
                        {
                            primaryKeyValue = valueExpression;
                        }
                        else
                        {
                            primaryKeyValue = Expression.Call(Expression.Constant(this), method, valueExpression, Expression.Constant(PrimaryKeyType.Composite));
                        }
                    }
                    else
                    {
                        primaryKeyValue = Expression.Call(MethodInfoFastRef.ConvertChangeTypeMethod, Expression.Convert(valueExpression, typeof(object)), Expression.Constant(propertyInfo.PropertyType));
                    }

                    var newExpression = Expression.New
                                        (
                        constructor,
                        Expression.Constant(propertyInfo.PropertyType),
                        Expression.Constant(property.PropertyName),
                        Expression.Constant(property.PersistedName),
                        Expression.Constant(property.PropertyName.GetHashCode()),
                        Expression.Convert(primaryKeyValue, typeof(object))
                                        );

                    initializers.Add(newExpression);
                }

                var body = Expression.NewArrayInit(typeof(ObjectPropertyValue), initializers);

                var lambdaExpression = Expression.Lambda(typeof(Func <object, ObjectPropertyValue[]>), body, parameter);

                func = (Func <object, ObjectPropertyValue[]>)lambdaExpression.Compile();

                this.objectPropertyValuesByAnonymousKeyFuncByType = this.objectPropertyValuesByAnonymousKeyFuncByType.Clone(key, func);
            }

            return(func(primaryKey));
        }
Example #8
0
        protected internal ObjectPropertyValue[] GetObjectPropertyValuesForPrimaryKeyColumns <T>(object[] primaryKeyValues)
        {
            if (primaryKeyValues == null)
            {
                throw new ArgumentNullException(nameof(primaryKeyValues));
            }

            if (primaryKeyValues.All(c => c == null))
            {
                return(null);
            }

            var objectTypeHandle = typeof(T).TypeHandle;

            if (!this.objectPropertyValuesByColumnValuesFuncByType.TryGetValue(objectTypeHandle, out var func))
            {
                var typeDescriptor = this.TypeDescriptorProvider.GetTypeDescriptor(typeof(T));

                var parameter   = Expression.Parameter(typeof(object[]));
                var constructor = ConstructorInfoFastRef.ObjectPropertyValueConstructor;

                var index        = 0;
                var initializers = new List <Expression>();

                foreach (var property in typeDescriptor.PrimaryKeyProperties)
                {
                    Expression convertedValue;
                    var        propertyInfo = DataAccessObjectTypeBuilder.GetPropertyInfo(GetConcreteTypeFromDefinitionType(typeDescriptor.Type), property.PropertyName);

                    if (property.PropertyType.IsDataAccessObjectType())
                    {
                        var columnInfos = QueryBinder.GetPrimaryKeyColumnInfos(this.TypeDescriptorProvider, property.PropertyTypeTypeDescriptor);
                        var args        = new Expression[columnInfos.Length];

                        for (var i = 0; i < columnInfos.Length; i++)
                        {
                            args[i] = Expression.Convert(Expression.Constant(primaryKeyValues[index + i]), typeof(object));
                        }

                        index += columnInfos.Length;

                        convertedValue = Expression.Call(Expression.Constant(this), MethodInfoFastRef.DataAccessModelGetReferenceByPrimaryKeyColumnsMethod.MakeGenericMethod(property.PropertyType), Expression.NewArrayInit(typeof(object), args));
                    }
                    else
                    {
                        var valueExpression = Expression.Convert(Expression.ArrayIndex(parameter, Expression.Constant(index)), typeof(object));

                        convertedValue = Expression.Call(MethodInfoFastRef.ConvertChangeTypeMethod, valueExpression, Expression.Constant(propertyInfo.PropertyType));
                    }

                    var newExpression = Expression.New(constructor, Expression.Constant(propertyInfo.PropertyType), Expression.Constant(property.PropertyName), Expression.Constant(property.PersistedName), Expression.Constant(property.PropertyName.GetHashCode()), convertedValue);

                    initializers.Add(newExpression);
                    index++;
                }

                var body = Expression.NewArrayInit(typeof(ObjectPropertyValue), initializers);

                var lambdaExpression = Expression.Lambda(typeof(Func <object[], ObjectPropertyValue[]>), body, parameter);

                func = (Func <object[], ObjectPropertyValue[]>)lambdaExpression.Compile();

                this.objectPropertyValuesByColumnValuesFuncByType = this.objectPropertyValuesByColumnValuesFuncByType.Clone(objectTypeHandle, func);
            }

            return(func(primaryKeyValues));
        }
Example #9
0
        protected internal ObjectPropertyValue[] GetObjectPropertyValues <K>(Type type, K primaryKey, PrimaryKeyType primaryKeyType = PrimaryKeyType.Auto)
        {
            if (Equals(primaryKey, default(K)) && typeof(K).IsClass)
            {
                throw new ArgumentNullException(nameof(primaryKey));
            }

            var idType     = primaryKey.GetType();
            var objectType = primaryKey.GetType();
            Func <object, ObjectPropertyValue[]> func;

            if (!this.propertyInfoAndValueGetterFuncByType.TryGetValue(objectType, out func))
            {
                var isSimpleKey    = false;
                var typeDescriptor = this.TypeDescriptorProvider.GetTypeDescriptor(type);
                var idPropertyType = typeDescriptor.GetPropertyDescriptorByPropertyName("Id").PropertyType;

                if (primaryKeyType == PrimaryKeyType.Single || TypeDescriptor.IsSimpleType(idType) || (idPropertyType.IsAssignableFrom(idType) && primaryKeyType == PrimaryKeyType.Auto))
                {
                    isSimpleKey = true;
                }

                if (isSimpleKey && typeDescriptor.PrimaryKeyCount != 1)
                {
                    throw new InvalidOperationException("Composite primary key expected");
                }

                var parameter   = Expression.Parameter(typeof(object));
                var constructor = ConstructorInfoFastRef.ObjectPropertyValueConstructor;

                var initializers = new List <Expression>();

                foreach (var property in typeDescriptor.PrimaryKeyProperties)
                {
                    var isObjectType = property.PropertyType.IsDataAccessObjectType();

                    Expression valueExpression;

                    if (isSimpleKey)
                    {
                        valueExpression = parameter;
                    }
                    else
                    {
                        valueExpression = Expression.Convert(Expression.PropertyOrField(Expression.Convert(parameter, objectType), property.PropertyName), typeof(object));
                    }

                    var propertyInfo = DataAccessObjectTypeBuilder.GetPropertyInfo(this.GetConcreteTypeFromDefinitionType(typeDescriptor.Type), property.PropertyName);

                    var newExpression = Expression.New
                                        (
                        constructor,
                        Expression.Constant(propertyInfo.PropertyType),
                        Expression.Constant(property.PropertyName),
                        Expression.Constant(property.PersistedName),
                        Expression.Constant(property.PropertyName.GetHashCode()),
                        isObjectType ? (Expression)Expression.Convert(valueExpression, propertyInfo.PropertyType) : (Expression)Expression.Call(MethodInfoFastRef.ConvertChangeTypeMethod, valueExpression, Expression.Constant(propertyInfo.PropertyType))
                                        );

                    initializers.Add(newExpression);
                }

                var body = Expression.NewArrayInit(typeof(ObjectPropertyValue), initializers);

                var lambdaExpression = Expression.Lambda(typeof(Func <object, ObjectPropertyValue[]>), body, parameter);

                func = (Func <object, ObjectPropertyValue[]>)lambdaExpression.Compile();

                var newPropertyInfoAndValueGetterFuncByType = new Dictionary <Type, Func <object, ObjectPropertyValue[]> >(this.propertyInfoAndValueGetterFuncByType);
                newPropertyInfoAndValueGetterFuncByType[objectType] = func;

                this.propertyInfoAndValueGetterFuncByType = newPropertyInfoAndValueGetterFuncByType;
            }

            return(func(primaryKey));
        }
Example #10
0
        private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration)
        {
            DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder;
            var serializedConfiguration = XmlSerializer <DataAccessModelConfigurationUniqueKey> .New().SerializeToString(new DataAccessModelConfigurationUniqueKey(configuration));

            var filename = GetFileName(typeDescriptorProvider, configuration.GeneratedAssembliesSaveDirectory, serializedConfiguration, out var fullhash);

            if (configuration.SaveAndReuseGeneratedAssemblies ?? false)
            {
                if (filename != null && File.Exists(filename))
                {
                    var candidate = Assembly.LoadFile(filename);

                    if (ReadResource(candidate, "configuration.xml") == serializedConfiguration &&
                        ReadResource(candidate, "sha1.txt") == fullhash)
                    {
                        return(candidate);
                    }
                }
            }

            var filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename);
            var typeDescriptors          = typeDescriptorProvider.GetTypeDescriptors();
            var assemblyName             = new AssemblyName(filenameWithoutExtension);
            var assemblyBuilder          = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetDirectoryName(filename));
            var moduleBuilder            = assemblyBuilder.DefineDynamicModule(filenameWithoutExtension, filenameWithoutExtension + ".dll");

            assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(TypeUtils.GetConstructor(() => new GeneratedAssemblyAttribute()), Type.EmptyTypes));

            var propertiesBuilder    = moduleBuilder.DefineType("$$$DataAccessModelProperties", TypeAttributes.Class, typeof(object));
            var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder, moduleBuilder, propertiesBuilder);

            var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder);

            dataAccessModelTypeBuilder.BuildTypePhase1(typeDescriptorProvider.DataAccessModelType);

            foreach (var typeDescriptor in typeDescriptors)
            {
                dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type);
                dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1));
            }

            foreach (var typeDescriptor in typeDescriptors)
            {
                dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type];
                dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2));
            }

            assemblyBuildContext.DataAccessModelPropertiesTypeBuilder.CreateType();
            assemblyBuildContext.FinishConstantsContainer();
            assemblyBuildContext.ConstantsContainer.CreateType();

            dataAccessModelTypeBuilder.BuildTypePhase2();

#if DEBUG
            const bool isInDebugMode = true;
#else
            const bool isInDebugMode = false;
#endif

            var saveAssembly = configuration.SaveAndReuseGeneratedAssemblies ?? !isInDebugMode;

            if (saveAssembly)
            {
                try
                {
                    moduleBuilder.DefineManifestResource("configuration.xml", new MemoryStream(Encoding.UTF8.GetBytes(serializedConfiguration)), ResourceAttributes.Public);
                    moduleBuilder.DefineManifestResource("sha1.txt", new MemoryStream(Encoding.UTF8.GetBytes(fullhash)), ResourceAttributes.Public);

                    assemblyBuilder.Save(Path.GetFileName(filename));
                }
                catch
                {
                }
            }

            return(assemblyBuilder);
        }