1 //---------------------------------------------------------------------
2 // <copyright file="EntityDataSourceMemberPath.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
11 using System.Collections.Generic;
14 using System.Data.EntityClient;
15 using System.Data.Metadata.Edm;
16 using System.Diagnostics;
17 using System.Globalization;
18 using System.Reflection;
19 using System.Data.Common;
20 using System.Data.Objects;
22 namespace System.Web.UI.WebControls
25 /// A glorified linked list. Describes a chain of properties from a primitive
26 /// type to a root entity.
28 class EntityDataSourceMemberPath
30 private readonly EdmProperty property;
31 private readonly PropertyInfo propertyInfo;
32 private readonly EntityDataSourceMemberPath parent;
33 private readonly bool isLocallyInteresting;
34 private readonly Type clrType;
35 private readonly bool isKey;
37 internal EntityDataSourceMemberPath(MetadataWorkspace ocWorkspace, EntityDataSourceMemberPath parent, EdmProperty property, bool isLocallyInteresting)
39 EntityDataSourceUtil.CheckArgumentNull(ocWorkspace, "ocWorkspace");
40 EntityDataSourceUtil.CheckArgumentNull(property, "property");
42 this.property = property;
44 this.isLocallyInteresting = isLocallyInteresting;
45 this.clrType = EntityDataSourceUtil.GetMemberClrType(ocWorkspace, property);
46 this.isKey = IsPropertyAKey(property);
48 // retrieve PropertyInfo (with respect to parent CLR type)
49 StructuralType parentType = property.DeclaringType;
50 Type parentClrType = EntityDataSourceUtil.GetClrType(ocWorkspace, parentType);
52 this.propertyInfo = EntityDataSourceUtil.GetPropertyInfo(parentClrType, this.property.Name);
56 /// Describes the member path in the form 'property1.property2...'. Use to
57 /// determine display name for nested properties in the EDSC.
59 /// <returns>Description of the </returns>
60 internal string GetDescription()
62 string prefix = null == this.parent ? string.Empty : this.parent.GetDescription() + ".";
63 return prefix + this.property.Name;
67 /// Indicates whether original values of this member should be preserved.
69 internal bool IsInteresting
73 // a member path is interesting if anything along the path is interesting
74 return this.isLocallyInteresting || (null != this.parent && this.parent.IsInteresting);
79 /// Indicates whether this member represents a primary key value.
83 get { return this.isKey; }
87 /// Indicates whether this member can be assigned a value of null.
89 internal bool IsNullable
91 get { return this.property.Nullable; }
94 internal bool IsScalar
96 get { return EntityDataSourceUtil.IsScalar(this.property.TypeUsage.EdmType); }
100 /// Gets the CLR type of the last member in the path.
102 internal Type ClrType
104 get { return this.clrType; }
107 internal object GetValue(EntityDataSourceWrapper entity)
109 object parentObjectValue = GetParentObjectValue(entity, false /* initialize */);
110 if (null == parentObjectValue)
112 // use convention that property of null is null
118 object propertyValue = this.propertyInfo.GetValue(parentObjectValue, new object[] { });
120 return propertyValue;
124 internal void SetValue(EntityDataSourceWrapper entity, object value)
126 object parentObjectValue = GetParentObjectValue(entity, true /* initialize */);
128 // set property value on parent
129 this.propertyInfo.SetValue(parentObjectValue, value, new object[] { });
132 private object Initialize(EntityDataSourceWrapper entity)
134 // get parent's value
135 object parentObjectValue = GetParentObjectValue(entity, true /* initialize */);
137 // construct type instance for this property
138 object propertyValue = EntityDataSourceUtil.InitializeType(this.ClrType);
141 this.propertyInfo.SetValue(parentObjectValue, propertyValue, new object[] { });
143 return propertyValue;
146 private object GetParentObjectValue(EntityDataSourceWrapper entity, bool initialize)
148 // get parent's value
149 object parentObjectValue;
151 if (null == this.parent)
153 // at the top level, the entity is the value
154 parentObjectValue = entity.WrappedEntity;
158 parentObjectValue = this.parent.GetValue(entity);
160 if (null == parentObjectValue && initialize)
162 parentObjectValue = this.parent.Initialize(entity);
166 return parentObjectValue;
169 internal string GetEntitySqlValue()
171 // it.[member1].[member2]...
176 prefix = parent.GetEntitySqlValue();
180 prefix = EntityDataSourceUtil.EntitySqlElementAlias;
183 string eSql = prefix + "." + EntityDataSourceUtil.QuoteEntitySqlIdentifier(this.property.Name);
188 private bool IsPropertyAKey(EdmProperty property)
191 EntityType entityType = property.DeclaringType as EntityType;
192 if (null != entityType)
194 isKey = entityType.KeyMembers.Contains(property);
199 public override string ToString()
201 string prefix = null == this.parent ? string.Empty : this.parent.ToString() + "->";
202 return prefix + this.property.Name;