Пример #1
0
 /// <summary>
 /// Captures the proxy holder associated with this instance.
 /// </summary>
 void CaptureProxy()
 {
     if (!_ProxyCaptured)
     {
         lock (ProxyGenerator.ProxyLock) { _ProxyHolder = ProxyGenerator.ProxyHolders.Find(_EntityType); }
         _ProxyCaptured = true;
         if (_ProxyHolder != null)
         {
             _EntityType = _ProxyHolder.ProxyType.BaseType;
         }
     }
 }
Пример #2
0
        /// <summary>
        /// Returns the proxy holder associated with the given map, creating and instance if it
        /// was not created yet. Returns null if no proxy type is needed because the type of the
        /// managed entities contains no lazy properties.
        /// </summary>
        internal static ProxyHolder Locate <T>(DataMap <T> map) where T : class
        {
            InitializeProxyGenerator();
            var list = GetLazyProperties <T>(map);
            var name = GetProxyTypeName <T>(list); if (name == null)
            {
                return(null);
            }

            ProxyHolder holder = null; lock (ProxyLock)

            {
                // If the appropriate holder exists, just return it...
                holder = ProxyHolders.Where(x => x.ProxyType.Name == name).FirstOrDefault();
                if (holder != null)
                {
                    list.Clear(); return(holder);
                }

                // Otherwise, create a new one - we cannot yet add it as its type is not set yet...
                holder = new ProxyHolder();

                // Capturing the lazy properties...
                foreach (var lazy in list)
                {
                    holder.LazyProperties.Add(lazy);
                }

                // Preparing the builders...
                Type        baseType = typeof(T);
                ILGenerator il       = null;

                var proxyBuilder = _ModuleBuilder.DefineType(name,
                                                             TypeAttributes.Public | TypeAttributes.AutoLayout |
                                                             TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass |
                                                             TypeAttributes.BeforeFieldInit,
                                                             baseType, null);

                // The fields that maintain whether the extended property is loaded or not...
                foreach (var lazy in holder.LazyProperties)
                {
                    lazy.LazyCompletedFlag = proxyBuilder.DefineField(lazy.Name + COMPLETEDFLAG_SUFFIX,
                                                                      typeof(bool),
                                                                      FieldAttributes.Public);
                }

                // Replicating the constructors on the extended type...
                var baseCons = baseType.GetConstructors(TypeEx.InstancePublicAndHidden);
                foreach (var baseCon in baseCons)
                {
                    var pars  = baseCon.GetParameters();
                    var types = pars.Select(x => x.ParameterType).ToArray();

                    var proxyCon = proxyBuilder.DefineConstructor(
                        baseCon.Attributes,
                        baseCon.CallingConvention,
                        types);

                    il = proxyCon.GetILGenerator(); foreach (var element in holder.LazyProperties)
                    {
                        il.Emit(OpCodes.Ldarg_0);
                        il.Emit(OpCodes.Ldc_I4_0);
                        il.Emit(OpCodes.Stfld, element.LazyCompletedFlag);
                    }
                    il.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < types.Length; i++)
                    {
                        il.Emit(OpCodes.Ldarg, i + 1);
                    }
                    il.Emit(OpCodes.Call, baseCon);
                    il.Emit(OpCodes.Ret);
                }

                // Replicating the virtual properties on the extended type...
                var onProxySetter = typeof(ProxyGenerator).GetMethod("OnProxySetter", BindingFlags.Public | BindingFlags.Static);
                var onProxyGetter = typeof(ProxyGenerator).GetMethod("OnProxyGetter", BindingFlags.Public | BindingFlags.Static);

                // Treating the lazy properties...
                foreach (var lazy in holder.LazyProperties)
                {
                    lazy.ExtendedProperty = proxyBuilder.DefineProperty(lazy.Name,
                                                                        lazy.OriginalProperty.Attributes,
                                                                        lazy.OriginalProperty.PropertyType, null);

                    lazy.SourceBackProperty = proxyBuilder.DefineProperty(lazy.Name + SOURCEBACK_SUFFIX,
                                                                          lazy.OriginalProperty.Attributes,
                                                                          lazy.OriginalProperty.PropertyType, null);

                    // The getter...
                    if (lazy.OriginalGetter != null && lazy.OriginalGetter.IsVirtual && !lazy.OriginalGetter.IsPrivate)
                    {
                        var sourceBackMethod = proxyBuilder.DefineMethod("get_" + lazy.SourceBackProperty.Name,
                                                                         MethodAttributes.Public |
                                                                         MethodAttributes.SpecialName |
                                                                         MethodAttributes.HideBySig | MethodAttributes.Virtual,
                                                                         lazy.SourceBackProperty.PropertyType, null);

                        il = sourceBackMethod.GetILGenerator();
                        il.Emit(OpCodes.Ldarg_0);
                        il.Emit(OpCodes.Call, lazy.OriginalGetter);
                        il.Emit(OpCodes.Ret);

                        ((PropertyBuilder)lazy.SourceBackProperty).SetGetMethod(sourceBackMethod);

                        var extendedMethod = proxyBuilder.DefineMethod("get_" + lazy.ExtendedProperty.Name,
                                                                       MethodAttributes.Public |
                                                                       MethodAttributes.SpecialName |
                                                                       MethodAttributes.HideBySig | MethodAttributes.Virtual,
                                                                       lazy.ExtendedProperty.PropertyType, null);

                        il = extendedMethod.GetILGenerator();
                        il.Emit(OpCodes.Ldarg_0);
                        il.Emit(OpCodes.Ldstr, lazy.ExtendedProperty.Name);
                        il.Emit(OpCodes.Call, onProxyGetter);
                        il.Emit(OpCodes.Ret);

                        ((PropertyBuilder)lazy.ExtendedProperty).SetGetMethod(extendedMethod);
                    }

                    // The setter...
                    if (lazy.OriginalSetter != null && lazy.OriginalSetter.IsVirtual && !lazy.OriginalSetter.IsPrivate)
                    {
                        var sourceBackMethod = proxyBuilder.DefineMethod("set_" + lazy.SourceBackProperty.Name,
                                                                         MethodAttributes.Public |
                                                                         MethodAttributes.SpecialName |
                                                                         MethodAttributes.HideBySig | MethodAttributes.Virtual,
                                                                         null, new[] { lazy.SourceBackProperty.PropertyType });

                        il = sourceBackMethod.GetILGenerator();
                        il.Emit(OpCodes.Ldarg_0);
                        il.Emit(OpCodes.Ldarg_1);
                        il.Emit(OpCodes.Call, lazy.OriginalSetter);
                        il.Emit(OpCodes.Ret);

                        ((PropertyBuilder)lazy.SourceBackProperty).SetSetMethod(sourceBackMethod);

                        var extendedMethod = proxyBuilder.DefineMethod("Set_" + lazy.ExtendedProperty.Name,
                                                                       MethodAttributes.Public |
                                                                       MethodAttributes.SpecialName |
                                                                       MethodAttributes.HideBySig | MethodAttributes.Virtual,
                                                                       null, new[] { lazy.ExtendedProperty.PropertyType });

                        il = extendedMethod.GetILGenerator();
                        il.Emit(OpCodes.Ldarg_0);
                        il.Emit(OpCodes.Ldarg_1);
                        il.Emit(OpCodes.Ldstr, lazy.ExtendedProperty.Name);
                        il.Emit(OpCodes.Call, onProxySetter);
                        il.Emit(OpCodes.Ret);

                        ((PropertyBuilder)lazy.ExtendedProperty).SetSetMethod(extendedMethod);
                    }
                }

                // Generating the type...
                holder.ProxyType = proxyBuilder.CreateType();

                // Before releasing the lock let's cache some relevant information...
                var type = holder.ProxyType; foreach (var lazy in holder.LazyProperties)
                {
                    lazy.LazyCompletedFlag = type.GetField(lazy.LazyCompletedFlag.Name, TypeEx.InstancePublicAndHidden);

                    lazy.ExtendedProperty = type.GetProperty(lazy.ExtendedProperty.Name, TypeEx.InstancePublicAndHidden);
                    lazy.ExtendedGetter   = lazy.ExtendedProperty == null ? null : lazy.ExtendedProperty.GetGetMethod(nonPublic: true);
                    lazy.ExtendedSetter   = lazy.ExtendedProperty == null ? null : lazy.ExtendedProperty.GetSetMethod(nonPublic: true);

                    lazy.SourceBackProperty = type.GetProperty(lazy.SourceBackProperty.Name, TypeEx.InstancePublicAndHidden);
                    lazy.SourceBackGetter   = lazy.SourceBackProperty == null ? null : lazy.SourceBackProperty.GetGetMethod(nonPublic: true);
                    lazy.SourceBackSetter   = lazy.SourceBackProperty == null ? null : lazy.SourceBackProperty.GetSetMethod(nonPublic: true);
                }

                // Now we can add the holder into the collection as we have set its type...
                ProxyHolders.Add(holder);
            }

            return(holder);
        }
Пример #3
0
		/// <summary>
		/// Captures the proxy holder associated with this instance.
		/// </summary>
		void CaptureProxy()
		{
			if (!_ProxyCaptured)
			{
				lock (ProxyGenerator.ProxyLock) { _ProxyHolder = ProxyGenerator.ProxyHolders.Find(_EntityType); }
				_ProxyCaptured = true;
				if (_ProxyHolder != null) _EntityType = _ProxyHolder.ProxyType.BaseType;
			}
		}