public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) { if (objectType == null && instance != null) { objectType = instance.GetType(); } if (this._type != objectType) { // In inheritance scenarios, we might be called to provide a descriptor // for a derived Type. In that case, we just return base. return(base.GetTypeDescriptor(objectType, instance)); } if (this._customTypeDescriptor == null) { // CLR, buddy class type descriptors this._customTypeDescriptor = base.GetTypeDescriptor(objectType, instance); // EF, any other custom type descriptors provided through DomainServiceDescriptionProviders. this._customTypeDescriptor = this._descriptionProvider.GetTypeDescriptor(objectType, this._customTypeDescriptor); // initialize FK members AFTER our type descriptors have chained HashSet <string> foreignKeyMembers = this.GetForeignKeyMembers(); // if any FK member of any association is also part of the primary key, then the key cannot be marked // Editable(false) bool keyIsEditable = false; foreach (PropertyDescriptor pd in this._customTypeDescriptor.GetProperties()) { if (pd.Attributes[typeof(KeyAttribute)] != null && foreignKeyMembers.Contains(pd.Name)) { keyIsEditable = true; break; } } if (DomainTypeDescriptor.ShouldRegister(this._customTypeDescriptor, keyIsEditable, foreignKeyMembers)) { // Extend the chain with one more descriptor. this._customTypeDescriptor = new DomainTypeDescriptor(objectType, this._customTypeDescriptor, keyIsEditable, foreignKeyMembers); } } return(this._customTypeDescriptor); }
private ICollection <PropertyDescriptor> CreateProjectionProperties(IEnumerable <PropertyDescriptor> existingProperties) { // Get the map of projection includes for each property List <PropertyDescriptor> projectionProperties = new List <PropertyDescriptor>(); Dictionary <PropertyDescriptor, IncludeAttribute[]> includeMap = DomainTypeDescriptor.GetProjectionIncludeMap(this._entityType, existingProperties); if (includeMap.Count == 0) { return(projectionProperties); } // for each existing property add projection properties for any member projections foreach (PropertyDescriptor pd in existingProperties) { IncludeAttribute[] memberProjections; includeMap.TryGetValue(pd, out memberProjections); if (memberProjections == null) { // no member projections for this property continue; } foreach (IncludeAttribute memberProjection in memberProjections) { // If the projection member already exists as a property on the source type // skip, otherwise we'll generate a duplicate if (existingProperties.SingleOrDefault(p => p.Name == memberProjection.MemberName) != null) { continue; } // Drill through the projection path to get the target property PropertyDescriptor targetProperty = pd; foreach (string pathMember in memberProjection.Path.Split('.')) { if (targetProperty.PropertyType == this._entityType) { // avoid recursion targetProperty = existingProperties.SingleOrDefault(p => p.Name == pathMember); } else { targetProperty = TypeDescriptor.GetProperties(targetProperty.PropertyType)[pathMember]; } if (targetProperty == null) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidMemberProjection_Path, memberProjection.Path, pd.PropertyType, pd.Name)); } } // verify the projected type is a supported type if (!TypeUtility.IsPredefinedType(targetProperty.PropertyType)) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.InvalidMemberProjection_InvalidProjectedType, targetProperty.ComponentType, targetProperty.Name, pd.PropertyType, pd.Name)); } // add the virtual projection property projectionProperties.Add(new MemberProjectionPropertyDescriptor(pd, targetProperty, memberProjection)); } } return(projectionProperties); }