Ejemplo n.º 1
0
 /// <summary>
 /// 构造一个代理对象。
 /// </summary>
 /// <returns></returns>
 public static TEntity New()
 {
     return((TEntity)EntityCompiler.NewProxy(typeof(TEntity)));
 }
        // <summary>
        // Processes the given context type to determine the DbSet or IDbSet
        // properties and collect root entity types from those properties.  Also, delegates are
        // created to initialize any of these properties that have public setters.
        // If the type has been processed previously in the app domain, then all this information
        // is returned from a cache.
        // </summary>
        // <returns> A dictionary of potential entity type to the list of the names of the properties that used the type. </returns>
        private Dictionary <Type, List <string> > GetSets()
        {
            EntityContextTypesInitializersPair setsInfo;
            var contextType = _context.GetType();

            if (!_objectSetInitializers.TryGetValue(contextType, out setsInfo))
            {
                // It is possible that multiple threads will enter this code and create the list
                // and the delegates.  However, the result will always be the same so we may, in
                // the rare cases in which this happens, do some work twice, but functionally the
                // outcome will be correct.

                var dbContextParam = Expression.Parameter(typeof(EntityContext), "dbContext");
                var initDelegates  = new List <Action <EntityContext> >();

                var typeMap = new Dictionary <Type, List <string> >();

                // Properties declared directly on DbContext such as Database are skipped
                foreach (var propertyInfo in contextType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                         .Where(p => p.GetIndexParameters().Length == 0 &&
                                p.DeclaringType != typeof(EntityContext)))
                {
                    var entityType = GetSetType(propertyInfo.PropertyType);
                    if (entityType != null)
                    {
                        // We validate immediately because a DbSet/IDbSet must be of
                        // a valid entity type since otherwise you could never use an instance.
                        if (!entityType.IsValidStructuralType())
                        {
                            //throw Error.InvalidEntityType(entityType);
                        }

                        List <string> properties;
                        if (!typeMap.TryGetValue(entityType, out properties))
                        {
                            properties          = new List <string>();
                            typeMap[entityType] = properties;
                        }

                        properties.Add(propertyInfo.Name);

                        var setter = propertyInfo.GetSetMethod();
                        if (setter != null && setter.IsPublic)
                        {
                            var setMethod = SetMethod.MakeGenericMethod(entityType);

                            var newExpression = Expression.Call(dbContextParam, setMethod);
                            var setExpression = Expression.Call(
                                Expression.Convert(dbContextParam, contextType), setter, newExpression);
                            initDelegates.Add(
                                Expression.Lambda <Action <EntityContext> >(setExpression, dbContextParam).Compile());
                        }
                    }
                }

                Action <EntityContext> initializer = dbContext =>
                {
                    foreach (var initer in initDelegates)
                    {
                        initer(dbContext);
                    }
                };

                setsInfo = new EntityContextTypesInitializersPair(typeMap, initializer);
                EntityCompiler.CompileContextTypes(contextType, typeMap.Keys.ToArray());

                // If TryAdd fails it just means some other thread got here first, which is okay
                // since the end result is the same info anyway.
                _objectSetInitializers.TryAdd(_context.GetType(), setsInfo);
            }

            return(setsInfo.EntityTypeToPropertyNameMap);
        }