private static IClrCollectionAccessor CreateGeneric <TEntity, TCollection, TElement>(PropertyInfo property)
            where TEntity : class
            where TCollection : class, ICollection <TElement>
        {
            var getterDelegate = (Func <TEntity, TCollection>)property.GetMethod.CreateDelegate(typeof(Func <TEntity, TCollection>));

            Action <TEntity, TCollection> setterDelegate = null;
            Func <TEntity, Action <TEntity, TCollection>, TCollection> createAndSetDelegate = null;
            Func <TCollection> createDelegate = null;

            var setter = property.SetMethod;

            if (setter != null)
            {
                setterDelegate = (Action <TEntity, TCollection>)setter.CreateDelegate(typeof(Action <TEntity, TCollection>));

                var concreteType = new CollectionTypeFactory().TryFindTypeToInstantiate(typeof(TEntity), typeof(TCollection));

                if (concreteType != null)
                {
                    createAndSetDelegate = (Func <TEntity, Action <TEntity, TCollection>, TCollection>)_createAndSet
                                           .MakeGenericMethod(typeof(TEntity), typeof(TCollection), concreteType)
                                           .CreateDelegate(typeof(Func <TEntity, Action <TEntity, TCollection>, TCollection>));

                    createDelegate = (Func <TCollection>)_create
                                     .MakeGenericMethod(typeof(TCollection), concreteType)
                                     .CreateDelegate(typeof(Func <TCollection>));
                }
            }

            return(new ClrICollectionAccessor <TEntity, TCollection, TElement>(
                       property.Name, getterDelegate, setterDelegate, createAndSetDelegate, createDelegate));
        }
Esempio n. 2
0
        public void Returns_HashSet_if_assignable()
        {
            var factory = new CollectionTypeFactory();

            Assert.Same(typeof(HashSet <Random>), factory.TryFindTypeToInstantiate(typeof(ICollection <Random>)));

            Assert.Same(typeof(HashSet <Random>), factory.TryFindTypeToInstantiate(typeof(ISet <Random>)));
        }
Esempio n. 3
0
        private static IClrCollectionAccessor CreateGeneric <TEntity, TCollection, TElement>(INavigation navigation, MemberInfo memberInfo)
            where TEntity : class
            where TCollection : class, IEnumerable <TElement>
        {
            var entityParameter = Expression.Parameter(typeof(TEntity), "entity");
            var valueParameter  = Expression.Parameter(typeof(TCollection), "collection");

            var memberAccess = (Expression)Expression.MakeMemberAccess(entityParameter, memberInfo);

            if (memberAccess.Type != typeof(TCollection))
            {
                memberAccess = Expression.Convert(memberAccess, typeof(TCollection));
            }

            var getterDelegate = Expression.Lambda <Func <TEntity, TCollection> >(
                memberAccess,
                entityParameter).Compile();

            Action <TEntity, TCollection> setterDelegate = null;
            Func <TEntity, Action <TEntity, TCollection>, TCollection> createAndSetDelegate = null;
            Func <TCollection> createDelegate = null;

            var setterMemberInfo = navigation.GetMemberInfo(forConstruction: false, forSet: true);

            if (setterMemberInfo != null)
            {
                setterDelegate = Expression.Lambda <Action <TEntity, TCollection> >(
                    Expression.Assign(
                        Expression.MakeMemberAccess(
                            entityParameter,
                            setterMemberInfo),
                        Expression.Convert(
                            valueParameter,
                            setterMemberInfo.GetMemberType())),
                    entityParameter,
                    valueParameter).Compile();
            }

            var concreteType = new CollectionTypeFactory().TryFindTypeToInstantiate(typeof(TEntity), typeof(TCollection));

            if (concreteType != null)
            {
                if (setterDelegate != null)
                {
                    createAndSetDelegate = (Func <TEntity, Action <TEntity, TCollection>, TCollection>)_createAndSet
                                           .MakeGenericMethod(typeof(TEntity), typeof(TCollection), concreteType)
                                           .CreateDelegate(typeof(Func <TEntity, Action <TEntity, TCollection>, TCollection>));
                }

                createDelegate = (Func <TCollection>)_create
                                 .MakeGenericMethod(typeof(TCollection), concreteType)
                                 .CreateDelegate(typeof(Func <TCollection>));
            }

            return(new ClrICollectionAccessor <TEntity, TCollection, TElement>(
                       navigation.Name, getterDelegate, setterDelegate, createAndSetDelegate, createDelegate));
        }
Esempio n. 4
0
        private static IClrCollectionAccessor CreateGeneric <TEntity, TCollection, TElement>(INavigation navigation)
            where TEntity : class
            where TCollection : class, IEnumerable <TElement>
        {
            var property = navigation.GetPropertyInfo();

            var getterDelegate = (Func <TEntity, TCollection>)property.GetMethod.CreateDelegate(typeof(Func <TEntity, TCollection>));

            Action <TEntity, TCollection> setterDelegate = null;
            Func <TEntity, Action <TEntity, TCollection>, TCollection> createAndSetDelegate = null;
            Func <TCollection> createDelegate = null;

            var setterProperty = property.DeclaringType
                                 .GetPropertiesInHierarchy(property.Name)
                                 .FirstOrDefault(p => p.SetMethod != null);

            if (setterProperty != null)
            {
                setterDelegate = (Action <TEntity, TCollection>)property.SetMethod.CreateDelegate(typeof(Action <TEntity, TCollection>));
            }
            else
            {
                var fieldInfo = navigation.DeclaringEntityType.Model.GetMemberMapper().FindBackingField(navigation);
                if (fieldInfo != null)
                {
                    var entityParameter = Expression.Parameter(typeof(TEntity), "entity");
                    var valueParameter  = Expression.Parameter(typeof(TCollection), "collection");

                    setterDelegate = Expression.Lambda <Action <TEntity, TCollection> >(
                        Expression.Assign(
                            Expression.Field(entityParameter, fieldInfo),
                            valueParameter),
                        entityParameter,
                        valueParameter).Compile();
                }
            }

            if (setterDelegate != null)
            {
                var concreteType = new CollectionTypeFactory().TryFindTypeToInstantiate(typeof(TEntity), typeof(TCollection));

                if (concreteType != null)
                {
                    createAndSetDelegate = (Func <TEntity, Action <TEntity, TCollection>, TCollection>)_createAndSet
                                           .MakeGenericMethod(typeof(TEntity), typeof(TCollection), concreteType)
                                           .CreateDelegate(typeof(Func <TEntity, Action <TEntity, TCollection>, TCollection>));

                    createDelegate = (Func <TCollection>)_create
                                     .MakeGenericMethod(typeof(TCollection), concreteType)
                                     .CreateDelegate(typeof(Func <TCollection>));
                }
            }

            return(new ClrICollectionAccessor <TEntity, TCollection, TElement>(
                       property.Name, getterDelegate, setterDelegate, createAndSetDelegate, createDelegate));
        }
Esempio n. 5
0
        public void Returns_given_type_if_public_parameterless_constructor_available()
        {
            var factory = new CollectionTypeFactory();

            Assert.Same(typeof(CustomHashSet), factory.TryFindTypeToInstantiate(typeof(CustomHashSet)));
            Assert.Same(typeof(CustomList), factory.TryFindTypeToInstantiate(typeof(CustomList)));
            Assert.Same(typeof(HashSet <Random>), factory.TryFindTypeToInstantiate(typeof(HashSet <Random>)));
            Assert.Same(typeof(List <Random>), factory.TryFindTypeToInstantiate(typeof(List <Random>)));
            Assert.Same(typeof(ObservableCollection <Random>), factory.TryFindTypeToInstantiate(typeof(ObservableCollection <Random>)));
        }
        public void Returns_null_when_no_usable_concrete_type_found()
        {
            var factory = new CollectionTypeFactory();

            Assert.Null(factory.TryFindTypeToInstantiate(typeof(object), typeof(PrivateConstructor)));
            Assert.Null(factory.TryFindTypeToInstantiate(typeof(object), typeof(InternalConstructor)));
            Assert.Null(factory.TryFindTypeToInstantiate(typeof(object), typeof(ProtectedConstructor)));
            Assert.Null(factory.TryFindTypeToInstantiate(typeof(object), typeof(NoParameterlessConstructor)));
            Assert.Null(factory.TryFindTypeToInstantiate(typeof(object), typeof(Abstract)));
            Assert.Null(factory.TryFindTypeToInstantiate(typeof(object), typeof(object)));
            Assert.Null(factory.TryFindTypeToInstantiate(typeof(object), typeof(Random)));
        }
Esempio n. 7
0
        private static IClrCollectionAccessor CreateGeneric <TEntity, TCollection, TElement>(INavigationBase navigation)
            where TEntity : class
            where TCollection : class, IEnumerable <TElement>
            where TElement : class
        {
            var entityParameter = Expression.Parameter(typeof(TEntity), "entity");
            var valueParameter  = Expression.Parameter(typeof(TCollection), "collection");

            var memberInfoForRead = navigation.GetMemberInfo(forMaterialization: false, forSet: false);

            navigation.TryGetMemberInfo(forConstruction: false, forSet: true, out var memberInfoForWrite, out _);
            navigation.TryGetMemberInfo(forConstruction: true, forSet: true, out var memberInfoForMaterialization, out _);

            var memberAccessForRead = (Expression)Expression.MakeMemberAccess(entityParameter, memberInfoForRead);

            if (memberAccessForRead.Type != typeof(TCollection))
            {
                memberAccessForRead = Expression.Convert(memberAccessForRead, typeof(TCollection));
            }

            var getterDelegate = Expression.Lambda <Func <TEntity, TCollection> >(
                memberAccessForRead,
                entityParameter).Compile();

            Action <TEntity, TCollection>?setterDelegate = null;
            Action <TEntity, TCollection>?setterDelegateForMaterialization = null;
            Func <TEntity, Action <TEntity, TCollection>, TCollection>?createAndSetDelegate = null;
            Func <TCollection>?createDelegate = null;

            if (memberInfoForWrite != null)
            {
                setterDelegate = CreateSetterDelegate(entityParameter, memberInfoForWrite, valueParameter);
            }

            if (memberInfoForMaterialization != null)
            {
                setterDelegateForMaterialization = CreateSetterDelegate(entityParameter, memberInfoForMaterialization, valueParameter);
            }

            var concreteType = new CollectionTypeFactory().TryFindTypeToInstantiate(
                typeof(TEntity),
                typeof(TCollection),
                navigation.DeclaringEntityType.Model[CoreAnnotationNames.FullChangeTrackingNotificationsRequiredAnnotation] != null);

            if (concreteType != null)
            {
                var isHashSet = concreteType.IsGenericType && concreteType.GetGenericTypeDefinition() == typeof(HashSet <>);
                if (setterDelegate != null ||
                    setterDelegateForMaterialization != null)
                {
                    if (isHashSet)
                    {
                        createAndSetDelegate = (Func <TEntity, Action <TEntity, TCollection>, TCollection>)_createAndSetHashSet
                                               .MakeGenericMethod(typeof(TEntity), typeof(TCollection), typeof(TElement))
                                               .CreateDelegate(typeof(Func <TEntity, Action <TEntity, TCollection>, TCollection>));
                    }
                    else if (IsObservableHashSet(concreteType))
                    {
                        createAndSetDelegate = (Func <TEntity, Action <TEntity, TCollection>, TCollection>)_createAndSetObservableHashSet
                                               .MakeGenericMethod(typeof(TEntity), typeof(TCollection), typeof(TElement))
                                               .CreateDelegate(typeof(Func <TEntity, Action <TEntity, TCollection>, TCollection>));
                    }
                    else
                    {
                        createAndSetDelegate = (Func <TEntity, Action <TEntity, TCollection>, TCollection>)_createAndSet
                                               .MakeGenericMethod(typeof(TEntity), typeof(TCollection), concreteType)
                                               .CreateDelegate(typeof(Func <TEntity, Action <TEntity, TCollection>, TCollection>));
                    }
                }

                if (isHashSet)
                {
                    createDelegate = (Func <TCollection>)_createHashSet
                                     .MakeGenericMethod(typeof(TCollection), typeof(TElement))
                                     .CreateDelegate(typeof(Func <TCollection>));
                }
                else if (IsObservableHashSet(concreteType))
                {
                    createDelegate = (Func <TCollection>)_createObservableHashSet
                                     .MakeGenericMethod(typeof(TCollection), typeof(TElement))
                                     .CreateDelegate(typeof(Func <TCollection>));
                }
                else
                {
                    createDelegate = (Func <TCollection>)_create
                                     .MakeGenericMethod(typeof(TCollection), concreteType)
                                     .CreateDelegate(typeof(Func <TCollection>));
                }
            }

            return(new ClrICollectionAccessor <TEntity, TCollection, TElement>(
                       navigation.Name,
                       getterDelegate,
                       setterDelegate,
                       setterDelegateForMaterialization,
                       createAndSetDelegate,
                       createDelegate));
        private static IClrCollectionAccessor CreateGeneric <TEntity, TCollection, TElement>(INavigation navigation)
            where TEntity : class
            where TCollection : class, IEnumerable <TElement>
            where TElement : class
        {
            Action <TEntity, TCollection> CreateSetterDelegate(
                ParameterExpression parameterExpression,
                MemberInfo memberInfo,
                ParameterExpression valueParameter1)
            => Expression.Lambda <Action <TEntity, TCollection> >(
                Expression.MakeMemberAccess(
                    parameterExpression,
                    memberInfo).Assign(
                    Expression.Convert(
                        valueParameter1,
                        memberInfo.GetMemberType())),
                parameterExpression,
                valueParameter1).Compile();

            var entityParameter = Expression.Parameter(typeof(TEntity), "entity");
            var valueParameter  = Expression.Parameter(typeof(TCollection), "collection");

            var memberInfoForRead            = navigation.GetMemberInfo(forMaterialization: false, forSet: false);
            var memberInfoForWrite           = navigation.GetMemberInfo(forMaterialization: false, forSet: true);
            var memberInfoForMaterialization = navigation.GetMemberInfo(forMaterialization: true, forSet: true);

            var memberAccessForRead = (Expression)Expression.MakeMemberAccess(entityParameter, memberInfoForRead);

            if (memberAccessForRead.Type != typeof(TCollection))
            {
                memberAccessForRead = Expression.Convert(memberAccessForRead, typeof(TCollection));
            }

            var getterDelegate = Expression.Lambda <Func <TEntity, TCollection> >(
                memberAccessForRead,
                entityParameter).Compile();

            Action <TEntity, TCollection> setterDelegate = null;
            Action <TEntity, TCollection> setterDelegateForMaterialization = null;
            Func <TEntity, Action <TEntity, TCollection>, TCollection> createAndSetDelegate = null;
            Func <TCollection> createDelegate = null;

            if (memberInfoForWrite != null)
            {
                setterDelegate = CreateSetterDelegate(entityParameter, memberInfoForWrite, valueParameter);
            }

            if (memberInfoForMaterialization != null)
            {
                setterDelegateForMaterialization = CreateSetterDelegate(entityParameter, memberInfoForMaterialization, valueParameter);
            }

            var concreteType = new CollectionTypeFactory().TryFindTypeToInstantiate(typeof(TEntity), typeof(TCollection));

            if (concreteType != null)
            {
                var isHashSet = concreteType.IsGenericType && concreteType.GetGenericTypeDefinition() == typeof(HashSet <>);
                if (setterDelegate != null ||
                    setterDelegateForMaterialization != null)
                {
                    if (isHashSet)
                    {
                        createAndSetDelegate = (Func <TEntity, Action <TEntity, TCollection>, TCollection>)_createAndSetHashSet
                                               .MakeGenericMethod(typeof(TEntity), typeof(TCollection), typeof(TElement))
                                               .CreateDelegate(typeof(Func <TEntity, Action <TEntity, TCollection>, TCollection>));
                    }
                    else if (IsObservableHashSet(concreteType))
                    {
                        createAndSetDelegate = (Func <TEntity, Action <TEntity, TCollection>, TCollection>)_createAndSetObservableHashSet
                                               .MakeGenericMethod(typeof(TEntity), typeof(TCollection), typeof(TElement))
                                               .CreateDelegate(typeof(Func <TEntity, Action <TEntity, TCollection>, TCollection>));
                    }
                    else
                    {
                        createAndSetDelegate = (Func <TEntity, Action <TEntity, TCollection>, TCollection>)_createAndSet
                                               .MakeGenericMethod(typeof(TEntity), typeof(TCollection), concreteType)
                                               .CreateDelegate(typeof(Func <TEntity, Action <TEntity, TCollection>, TCollection>));
                    }
                }

                if (isHashSet)
                {
                    createDelegate = (Func <TCollection>)_createHashSet
                                     .MakeGenericMethod(typeof(TCollection), typeof(TElement))
                                     .CreateDelegate(typeof(Func <TCollection>));
                }
                else if (IsObservableHashSet(concreteType))
                {
                    createDelegate = (Func <TCollection>)_createObservableHashSet
                                     .MakeGenericMethod(typeof(TCollection), typeof(TElement))
                                     .CreateDelegate(typeof(Func <TCollection>));
                }
                else
                {
                    createDelegate = (Func <TCollection>)_create
                                     .MakeGenericMethod(typeof(TCollection), concreteType)
                                     .CreateDelegate(typeof(Func <TCollection>));
                }
            }

            return(new ClrICollectionAccessor <TEntity, TCollection, TElement>(
                       navigation.Name,
                       getterDelegate,
                       setterDelegate,
                       setterDelegateForMaterialization,
                       createAndSetDelegate,
                       createDelegate));
        }