File: DynamicData\ModelProviders\DLinqDataModelProvider.cs
Project: ndp\fx\src\xsp\system\DynamicData\System.Web.DynamicData.csproj (System.Web.DynamicData)
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Linq;
using System.Linq;
using System.Reflection;
using LinqMetaTable = System.Data.Linq.Mapping.MetaTable;
using LinqMetaType = System.Data.Linq.Mapping.MetaType;
 
namespace System.Web.DynamicData.ModelProviders {
    internal sealed class DLinqDataModelProvider : DataModelProvider {
        private ReadOnlyCollection<TableProvider> _roTables;
        private Dictionary<PropertyInfo, DLinqColumnProvider> _columnLookup = new Dictionary<PropertyInfo, DLinqColumnProvider>();
 
        private Func<object> ContextFactory { get; set; }
 
        public DLinqDataModelProvider(object contextInstance, Func<object> contextFactory) {
            ContextFactory = contextFactory;
 
            DataContext context = (DataContext)contextInstance ?? (DataContext)CreateContext();
            ContextType = context.GetType();
 
            DLinqTables = new List<TableProvider>();
            foreach (PropertyInfo prop in ContextType.GetProperties()) {
                Type entityType = GetEntityType(prop);
 
                if (entityType != null) {
                    LinqMetaTable table = GetLinqTable(context, entityType);
                    ProcessTable(table, table.RowType, prop.Name, prop);
                }
            }
 
            DLinqTables.ForEach(t => ((DLinqTableProvider)t).Initialize());
 
            _roTables = new ReadOnlyCollection<TableProvider>(DLinqTables);
        }
 
        private LinqMetaTable GetLinqTable(DataContext context, Type entityType) {
            return context.Mapping.GetTables().First(t => t.RowType.Type == entityType);
        }
 
        private Type GetEntityType(PropertyInfo prop) {
            // 
            if (prop.PropertyType.IsGenericType &&
                prop.PropertyType.GetGenericTypeDefinition() == typeof(Table<>))
                return prop.PropertyType.GetGenericArguments()[0];
 
            return null;
        }
 
        private void ProcessTable(LinqMetaTable table, LinqMetaType rowType, string name, PropertyInfo prop) {
            DLinqTables.Add(new DLinqTableProvider(this, rowType, name, prop));
 
            foreach (LinqMetaType derivedType in rowType.DerivedTypes)
                ProcessTable(table, derivedType, derivedType.Name, prop);
        }
 
        internal Dictionary<PropertyInfo, DLinqColumnProvider> ColumnLookup {
            get {
                return _columnLookup;
            }
        }
 
        internal List<TableProvider> DLinqTables { get; private set; }
 
        public override object CreateContext() {
            return ContextFactory();
        }
 
        public override ReadOnlyCollection<TableProvider> Tables {
            get {
                return _roTables;
            }
        }
    }
}