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)); }
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>))); }
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)); }
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)); }
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))); }
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)); }