using System; using System.Collections; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Security.Permissions; using System.Security; using System.Runtime.CompilerServices; namespace System.Data.Linq.Mapping { using System.Data.Linq.Provider; using System.Diagnostics.CodeAnalysis; internal delegate V DGet(T t); internal delegate void DSet(T t, V v); internal delegate void DRSet(ref T t, V v); internal static class FieldAccessor { [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static MetaAccessor Create(Type objectType, FieldInfo fi) { if (!fi.ReflectedType.IsAssignableFrom(objectType)) throw Error.InvalidFieldInfo(objectType, fi.FieldType, fi); Delegate dget = null; Delegate drset = null; if (!objectType.IsGenericType) { DynamicMethod mget = new DynamicMethod( "xget_" + fi.Name, fi.FieldType, new Type[] { objectType }, true ); ILGenerator gen = mget.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldfld, fi); gen.Emit(OpCodes.Ret); dget = mget.CreateDelegate(typeof(DGet<,>).MakeGenericType(objectType, fi.FieldType)); DynamicMethod mset = new DynamicMethod( "xset_" + fi.Name, typeof(void), new Type[] { objectType.MakeByRefType(), fi.FieldType }, true ); gen = mset.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); if (!objectType.IsValueType) { gen.Emit(OpCodes.Ldind_Ref); } gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Stfld, fi); gen.Emit(OpCodes.Ret); drset = mset.CreateDelegate(typeof(DRSet<,>).MakeGenericType(objectType, fi.FieldType)); } return (MetaAccessor)Activator.CreateInstance( typeof(Accessor<,>).MakeGenericType(objectType, fi.FieldType), BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { fi, dget, drset }, null ); } class Accessor : MetaAccessor { DGet dget; DRSet drset; FieldInfo fi; internal Accessor(FieldInfo fi, DGet dget, DRSet drset) { this.fi = fi; this.dget = dget; this.drset = drset; } public override V GetValue(T instance) { if (this.dget != null) return this.dget(instance); return (V)fi.GetValue(instance); } public override void SetValue(ref T instance, V value) { if (this.drset != null) this.drset(ref instance, value); else this.fi.SetValue(instance, value); } } } internal static class PropertyAccessor { internal static MetaAccessor Create(Type objectType, PropertyInfo pi, MetaAccessor storageAccessor) { Delegate dset = null; Delegate drset = null; Type dgetType = typeof(DGet<,>).MakeGenericType(objectType, pi.PropertyType); MethodInfo getMethod = pi.GetGetMethod(true); Delegate dget = Delegate.CreateDelegate(dgetType, getMethod, true); if (dget == null) { throw Error.CouldNotCreateAccessorToProperty(objectType, pi.PropertyType, pi); } if (pi.CanWrite) { if (!objectType.IsValueType) { dset = Delegate.CreateDelegate(typeof(DSet<,>).MakeGenericType(objectType, pi.PropertyType), pi.GetSetMethod(true), true); } else { DynamicMethod mset = new DynamicMethod( "xset_" + pi.Name, typeof(void), new Type[] { objectType.MakeByRefType(), pi.PropertyType }, true ); ILGenerator gen = mset.GetILGenerator(); gen.Emit(OpCodes.Ldarg_0); if (!objectType.IsValueType) { gen.Emit(OpCodes.Ldind_Ref); } gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Call, pi.GetSetMethod(true)); gen.Emit(OpCodes.Ret); drset = mset.CreateDelegate(typeof(DRSet<,>).MakeGenericType(objectType, pi.PropertyType)); } } Type saType = (storageAccessor != null) ? storageAccessor.Type : pi.PropertyType; return (MetaAccessor)Activator.CreateInstance( typeof(Accessor<,,>).MakeGenericType(objectType, pi.PropertyType, saType), BindingFlags.Instance|BindingFlags.NonPublic, null, new object[] {pi, dget, dset, drset, storageAccessor}, null ); } class Accessor : MetaAccessor where V2 : V { PropertyInfo pi; DGet dget; DSet dset; DRSet drset; MetaAccessor storage; internal Accessor(PropertyInfo pi, DGet dget, DSet dset, DRSet drset, MetaAccessor storage) { this.pi = pi; this.dget = dget; this.dset = dset; this.drset = drset; this.storage = storage; } public override V GetValue(T instance) { return this.dget(instance); } public override void SetValue(ref T instance, V value) { if (this.dset != null) { this.dset(instance, value); } else if (this.drset != null) { this.drset(ref instance, value); } else if (this.storage != null) { this.storage.SetValue(ref instance, (V2)value); } else { throw Error.UnableToAssignValueToReadonlyProperty(this.pi); } } } } // deferred type accessors internal class LinkValueAccessor : MetaAccessor { MetaAccessor> acc; internal LinkValueAccessor(MetaAccessor> acc) { this.acc = acc; } public override bool HasValue(object instance) { Link link = this.acc.GetValue((T)instance); return link.HasValue; } public override bool HasAssignedValue(object instance) { Link link = this.acc.GetValue((T)instance); return link.HasAssignedValue; } public override bool HasLoadedValue(object instance) { Link link = this.acc.GetValue((T)instance); return link.HasLoadedValue; } public override V GetValue(T instance) { Link link = this.acc.GetValue(instance); return link.Value; } public override void SetValue(ref T instance, V value) { this.acc.SetValue(ref instance, new Link(value)); } } internal class LinkDefValueAccessor : MetaAccessor { MetaAccessor> acc; internal LinkDefValueAccessor(MetaAccessor> acc) { this.acc = acc; } public override V GetValue(T instance) { Link link = this.acc.GetValue(instance); return link.UnderlyingValue; } public override void SetValue(ref T instance, V value) { this.acc.SetValue(ref instance, new Link(value)); } } internal class LinkDefSourceAccessor : MetaAccessor> { MetaAccessor> acc; internal LinkDefSourceAccessor(MetaAccessor> acc) { this.acc = acc; } public override IEnumerable GetValue(T instance) { Link link = this.acc.GetValue(instance); return (IEnumerable)link.Source; } public override void SetValue(ref T instance, IEnumerable value) { Link link = this.acc.GetValue(instance); if (link.HasAssignedValue || link.HasLoadedValue) { throw Error.LinkAlreadyLoaded(); } this.acc.SetValue(ref instance, new Link(value)); } } internal class EntityRefValueAccessor : MetaAccessor where V : class { MetaAccessor> acc; internal EntityRefValueAccessor(MetaAccessor> acc) { this.acc = acc; } public override V GetValue(T instance) { EntityRef er = this.acc.GetValue(instance); return er.Entity; } public override void SetValue(ref T instance, V value) { this.acc.SetValue(ref instance, new EntityRef(value)); } public override bool HasValue(object instance) { EntityRef er = this.acc.GetValue((T)instance); return er.HasValue; } public override bool HasAssignedValue(object instance) { EntityRef er = this.acc.GetValue((T)instance); return er.HasAssignedValue; } public override bool HasLoadedValue(object instance) { EntityRef er = this.acc.GetValue((T)instance); return er.HasLoadedValue; } } internal class EntityRefDefValueAccessor : MetaAccessor where V : class { MetaAccessor> acc; internal EntityRefDefValueAccessor(MetaAccessor> acc) { this.acc = acc; } public override V GetValue(T instance) { EntityRef er = this.acc.GetValue(instance); return er.UnderlyingValue; } public override void SetValue(ref T instance, V value) { this.acc.SetValue(ref instance, new EntityRef(value)); } } internal class EntityRefDefSourceAccessor : MetaAccessor> where V : class { MetaAccessor> acc; internal EntityRefDefSourceAccessor(MetaAccessor> acc) { this.acc = acc; } public override IEnumerable GetValue(T instance) { EntityRef er = this.acc.GetValue(instance); return (IEnumerable)er.Source; } public override void SetValue(ref T instance, IEnumerable value) { EntityRef er = this.acc.GetValue(instance); if (er.HasAssignedValue || er.HasLoadedValue) { throw Error.EntityRefAlreadyLoaded(); } this.acc.SetValue(ref instance, new EntityRef(value)); } } internal class EntitySetValueAccessor : MetaAccessor> where V : class { MetaAccessor> acc; internal EntitySetValueAccessor(MetaAccessor> acc) { this.acc = acc; } public override EntitySet GetValue(T instance) { return this.acc.GetValue(instance); } public override void SetValue(ref T instance, EntitySet value) { EntitySet eset = this.acc.GetValue(instance); if (eset == null) { eset = new EntitySet(); this.acc.SetValue(ref instance, eset); } eset.Assign(value); } public override bool HasValue(object instance) { EntitySet es = this.acc.GetValue((T)instance); return es != null && es.HasValues; } public override bool HasAssignedValue(object instance) { EntitySet es = this.acc.GetValue((T)instance); return es != null && es.HasAssignedValues; } public override bool HasLoadedValue(object instance) { EntitySet es = this.acc.GetValue((T)instance); return es != null && es.HasLoadedValues; } } internal class EntitySetDefValueAccessor : MetaAccessor> where V : class { MetaAccessor> acc; internal EntitySetDefValueAccessor(MetaAccessor> acc) { this.acc = acc; } public override IEnumerable GetValue(T instance) { EntitySet eset = this.acc.GetValue(instance); return eset.GetUnderlyingValues(); } public override void SetValue(ref T instance, IEnumerable value) { EntitySet eset = this.acc.GetValue(instance); if (eset == null) { eset = new EntitySet(); this.acc.SetValue(ref instance, eset); } eset.Assign(value); } } internal class EntitySetDefSourceAccessor : MetaAccessor> where V : class { MetaAccessor> acc; internal EntitySetDefSourceAccessor(MetaAccessor> acc) { this.acc = acc; } public override IEnumerable GetValue(T instance) { EntitySet eset = this.acc.GetValue(instance); return (IEnumerable)eset.Source; } public override void SetValue(ref T instance, IEnumerable value) { EntitySet eset = this.acc.GetValue(instance); if (eset == null) { eset = new EntitySet(); this.acc.SetValue(ref instance, eset); } eset.SetSource(value); } } }