< Summary

Information
Class: ImpromptuInterface.Build.ActLikeMaker
Assembly: ImpromptuInterface
File(s): /home/runner/work/impromptu-interface/impromptu-interface/ImpromptuInterface/src/EmitProxy/ActLikeMaker.cs
Line coverage
93%
Covered lines: 852
Uncovered lines: 57
Coverable lines: 909
Total lines: 1847
Line coverage: 93.7%
Branch coverage
83%
Covered branches: 267
Total branches: 320
Branch coverage: 83.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
ActLike(...)100%11100%
Create()100%210%
Create(...)100%22100%
AllActLike(...)100%11100%
InitializeProxy(...)100%11100%
ActLike(...)100%11100%
ActLikeProperties(...)100%11100%
DynamicActLike(...)100%11100%
.ctor()100%11100%
RecursiveActLikeForProxy(...)100%11100%
.ctor(...)50%22100%
get_Builder()100%22100%
BuildType(...)100%22100%
BuildType(...)100%22100%
PreLoadProxy(...)0%156120%
PreLoadProxiesFromAssembly(...)0%2040%
BuildTypeHelper(...)100%22100%
MakePropertyDescribedProperty(...)100%11100%
DefineCallsiteFieldForMethod(...)100%11100%
DefineCallsiteField(...)100%11100%
.ctor(...)100%11100%
.ctor(...)100%210%
Equals(...)50%66100%
Equals(...)50%66100%
GetHashCode()100%11100%
BuildTypeHelper(...)100%181893.93%
FlattenGenericParameters(...)90%1010100%
ReplaceTypeWithGenericBuilder(...)85%202091.66%
CustomAttributeTypeArgument(...)100%22100%
.cctor()100%11100%
GenericDelegateType(...)42.85%561440%
GetAttributeBuilder(...)50%12861.9%
MakeMethod(...)90%303098.5%
DefineBuilderForCallSite(...)100%11100%
GetParamTypes(...)71.42%141486.95%
EmitMethodBody(...)100%2020100%
MakeProperty(...)100%66100%
.ctor()100%11100%
.ctor()100%11100%
MakeEvent(...)100%1616100%
EmitRemoveEvent(...)100%88100%
EmitAddEvent(...)100%1010100%
MakePropertyHelper(...)96.87%3232100%
.ctor()100%11100%
get_CallSiteName()100%11100%
.ctor()100%11100%
ToCustomAttributeBuilder(...)100%11100%
EmitProperty(...)96.87%3232100%
UpdateCallsiteFuncType(...)75%44100%
ReduceToElementType(...)83.33%66100%
EmitCallSiteFuncType(...)100%210%
GenerateCallSiteFuncType(...)100%2020100%
GenerateFullDelegate(...)70%1010100%
AttributesForParam(...)100%11100%
GenerateAssembly(...)100%11100%

File(s)

/home/runner/work/impromptu-interface/impromptu-interface/ImpromptuInterface/src/EmitProxy/ActLikeMaker.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4using System.Collections.ObjectModel;
 5using System.IO;
 6using System.Linq;
 7using System.Linq.Expressions;
 8using System.Reflection;
 9using System.Reflection.Emit;
 10using System.Runtime.CompilerServices;
 11using ImpromptuInterface.Optimization;
 12using Microsoft.CSharp.RuntimeBinder;
 13
 14namespace ImpromptuInterface.Build
 15{
 16
 17#if NETFRAMEWORK
 18    public class SaveableActLikeMaker : ActLikeMaker
 19    {
 20        public SaveableActLikeMaker(AssemblyBuilderAccess access, string assemblyName = null) : base(access, assemblyNam
 21        {
 22
 23        }
 24
 25        public void Save(string dirPath = null)
 26        {
 27            if (AssemblyAccess.HasFlag(AssemblyBuilderAccess.Save))
 28            {
 29                if (dirPath == null)
 30                {
 31                    dirPath = "";
 32                }
 33                _ab.Save(Path.Combine(dirPath, $"{AssemblyName}.dll"));
 34            }
 35            else
 36            {
 37                throw new InvalidOperationException("AssemblyBuilder not set to be saveable");
 38            }
 39        }
 40    }
 41
 42#endif
 43    public class ActLikeMaker
 44    {
 45
 46
 47        public dynamic ActLike(object originalDynamic, params Type[] otherInterfaces)
 48        {
 2549            return new ActLikeCaster(originalDynamic, otherInterfaces) {Maker = this};
 50        }
 51
 52        public TInterface Create<TTarget, TInterface>() where TTarget : new() where TInterface : class
 53        {
 054            return this.ActLike<TInterface>(new TTarget());
 55        }
 56
 57        public TInterface Create<TTarget, TInterface>(params object[] args) where TInterface : class
 58        {
 1459            return this.ActLike(DynamicConstructor.Invoke(typeof(TTarget), args));
 60        }
 61
 62        public IEnumerable<TInterface> AllActLike<TInterface>(IEnumerable<object> originalDynamic, params Type[] otherIn
 63        {
 164            return originalDynamic.Select(it => this.ActLike<TInterface>(it, otherInterfaces));
 65        }
 66
 67
 68
 69        /// <summary>
 70        /// Private helper method that initializes the proxy.
 71        /// </summary>
 72        /// <param name="proxytype">The proxytype.</param>
 73        /// <param name="original">The original.</param>
 74        /// <param name="interfaces">The interfaces.</param>
 75        /// <param name="propertySpec">The property spec.</param>
 76        /// <returns></returns>
 77        internal static object InitializeProxy(Type proxytype, object original, IEnumerable<Type> interfaces =null, IDic
 78        {
 12979            var tProxy = (IActLikeProxyInitialize)Activator.CreateInstance(proxytype);
 12980            tProxy.Initialize(original, interfaces, propertySpec, maker);
 12981            return tProxy;
 82        }
 83
 84        public TInterface ActLike<TInterface>(object originalDynamic, params Type[] otherInterfaces) where TInterface : 
 85        {
 9686            originalDynamic = originalDynamic.GetTargetContext(out var tContext, out var tDummy);
 9687            tContext = tContext.FixContext();
 88
 9689            var tProxy = this.BuildType(tContext, typeof(TInterface), otherInterfaces);
 90
 91
 92
 9693            return
 9694                (TInterface)
 9695                InitializeProxy(tProxy, originalDynamic, new[] {typeof (TInterface)}.Concat(otherInterfaces), maker:this
 96        }
 97
 98        public dynamic ActLikeProperties(object originalDynamic, IDictionary<string, Type> propertySpec)
 99        {
 2100            originalDynamic = originalDynamic.GetTargetContext(out var tContext, out var tDummy);
 2101            tContext = tContext.FixContext();
 102
 2103            var tProxy = this.BuildType(tContext, propertySpec);
 104
 105
 106
 2107            return
 2108                InitializeProxy(tProxy, originalDynamic, propertySpec: propertySpec, maker: this);
 109        }
 110
 111        public dynamic DynamicActLike(object originalDynamic, params Type[] otherInterfaces)
 112        {
 31113            originalDynamic = originalDynamic.GetTargetContext(out var tContext, out var tDummy);
 31114            tContext = tContext.FixContext();
 115
 31116            var tProxy = this.BuildType(tContext, otherInterfaces.First(), otherInterfaces.Skip(1).ToArray());
 117
 31118            return InitializeProxy(tProxy, originalDynamic, otherInterfaces, maker: this);
 119
 120        }
 121
 122
 123
 124
 125
 126        protected ModuleBuilder _builder;
 127
 128        protected AssemblyBuilder _ab;
 2129        protected readonly IDictionary<TypeHash, Type> _typeHash = new Dictionary<TypeHash, Type>();
 2130        protected readonly object TypeCacheLock = new object();
 131
 2132        protected readonly IDictionary<TypeHash, Type> _delegateCache = new Dictionary<TypeHash, Type>();
 2133        protected readonly object DelegateCacheLock = new object();
 134
 2135        protected readonly MethodInfo ActLikeRec = typeof(ActLikeMaker).GetMethod(nameof(RecursiveActLikeForProxy),
 2136            new[] {typeof(ActLikeMaker), typeof(object) });
 137
 138        public static TInterface RecursiveActLikeForProxy<TInterface>(ActLikeMaker maker, object target) where TInterfac
 139        {
 12140            return maker.ActLike<TInterface>(target);
 141        }
 142
 143
 1144        internal ActLikeMaker()
 145        {
 1146            AssemblyAccess = AssemblyBuilderAccess.Run;
 1147            AssemblyName = $"{nameof(ImpromptuInterface)}DynamicAssembly";
 1148        }
 149
 150        public string AssemblyName { get; private set; }
 151
 1152        public ActLikeMaker(AssemblyBuilderAccess access, string assemblyName = null)
 153        {
 1154            AssemblyAccess = access;
 1155            if (assemblyName == null)
 156            {
 1157                assemblyName = $"{nameof(ImpromptuInterface)}_{Guid.NewGuid():N}";
 158            }
 159
 1160            AssemblyName = assemblyName;
 1161        }
 162
 163        ///<summary>
 164        /// Module Builder for building proxies
 165        ///</summary>
 166        private ModuleBuilder Builder
 167        {
 168            get
 169            {
 77170                if (_builder == null)
 171                {
 172
 2173                    GenerateAssembly(AssemblyName, AssemblyAccess, ref _ab, ref _builder);
 174                }
 77175                return _builder;
 176            }
 177        }
 178
 179
 180
 181
 182
 183        /// <summary>
 184        /// Builds the type for the proxy or returns from cache
 185        /// </summary>
 186        /// <param name="contextType">Type of the context.</param>
 187        /// <param name="mainInterface">The main interface.</param>
 188        /// <param name="otherInterfaces">The other interfaces.</param>
 189        /// <returns></returns>
 190        public Type BuildType(Type contextType, Type mainInterface, params Type[] otherInterfaces)
 191        {
 127192            lock (TypeCacheLock)
 193            {
 127194                contextType = contextType.FixContext();
 127195                var tNewHash = TypeHash.Create(contextType, new[] { mainInterface }.Concat(otherInterfaces).ToArray());
 196                Type tType;
 127197                if (!_typeHash.TryGetValue(tNewHash, out tType))
 198                {
 71199                    tType = BuildTypeHelper(Builder, contextType, new[] { mainInterface }.Concat(otherInterfaces).ToArra
 71200                    _typeHash[tNewHash] = tType;
 201                }
 202
 127203                return _typeHash[tNewHash];
 204            }
 205
 127206        }
 207
 208        /// <summary>
 209        /// Builds the type.
 210        /// </summary>
 211        /// <param name="contextType">Type of the context.</param>
 212        /// <param name="informalInterface">The informal interface.</param>
 213        /// <returns></returns>
 214        public Type BuildType(Type contextType, IDictionary<string, Type> informalInterface)
 215        {
 2216            lock (TypeCacheLock)
 217            {
 2218                var tNewHash = TypeHash.Create(contextType, informalInterface);
 2219                if (!_typeHash.TryGetValue(tNewHash, out var tType))
 220                {
 2221                    tType = BuildTypeHelper(Builder, contextType, informalInterface);
 222
 2223                    _typeHash[tNewHash] = tType;
 224                }
 225
 2226                return _typeHash[tNewHash];
 227            }
 228
 2229        }
 230
 231        /// <summary>
 232        /// Preloads a proxy for ActLike to use.
 233        /// </summary>
 234        /// <param name="proxyType">Type of the proxy.</param>
 235        /// <param name="attribute">The ActLikeProxyAttribute, if not provide it will be looked up.</param>
 236        /// <returns>Returns false if there already is a proxy registered for the same type.</returns>
 237        public bool PreLoadProxy(Type proxyType, ActLikeProxyAttribute attribute = null)
 238        {
 0239            var tSuccess = true;
 0240            if (attribute == null)
 0241                attribute = proxyType.GetCustomAttributes(typeof(ActLikeProxyAttribute), inherit: false).Cast<ActLikePro
 242
 0243            if (attribute == null)
 0244                throw new Exception("Proxy Type must have ActLikeProxyAttribute");
 245
 0246            if (!typeof(IActLikeProxyInitialize).IsAssignableFrom(proxyType))
 0247                throw new Exception("Proxy Type must implement IActLikeProxyInitialize");
 248
 0249            foreach (var tIType in attribute.Interfaces)
 250            {
 0251                if (!tIType.IsAssignableFrom(proxyType))
 252                {
 0253                    throw new Exception(String.Format("Proxy Type {0} must implement declared interfaces {1}", proxyType
 254                }
 255            }
 256
 0257            lock (TypeCacheLock)
 258            {
 0259                var tNewHash = TypeHash.Create(attribute.Context, attribute.Interfaces);
 260
 0261                if (!_typeHash.ContainsKey(tNewHash))
 262                {
 0263                    _typeHash[tNewHash] = proxyType;
 264                }
 265                else
 266                {
 0267                    tSuccess = false;
 268                }
 0269            }
 0270            return tSuccess;
 271        }
 272
 273        /// <summary>
 274        /// Preloads proxies that ActLike uses from assembly.
 275        /// </summary>
 276        /// <param name="assembly">The assembly.</param>
 277        /// <returns>Returns false if there already is a proxy registered for the same type.</returns>
 278        public bool PreLoadProxiesFromAssembly(Assembly assembly)
 279        {
 0280            var tSuccess = true;
 0281            var typesWithMyAttribute =
 0282                from tType in assembly.GetTypes()
 0283                let tAttributes = tType.GetCustomAttributes(typeof(ActLikeProxyAttribute), inherit: false)
 0284                where tAttributes != null && tAttributes.Length == 1
 0285                select new { Type = tType, Impromptu = tAttributes.Cast<ActLikeProxyAttribute>().Single() };
 0286            foreach (var tTypeCombo in typesWithMyAttribute)
 287            {
 0288                lock (TypeCacheLock)
 289                {
 0290                    if (!PreLoadProxy(tTypeCombo.Type, tTypeCombo.Impromptu))
 0291                        tSuccess = false;
 0292                }
 293            }
 0294            return tSuccess;
 295        }
 296
 297        private Type BuildTypeHelper(ModuleBuilder builder, Type contextType, IDictionary<string, Type> informalInterfac
 298        {
 299
 300
 2301            var tB = builder.DefineType(
 2302                $"ActLike_{"InformalInterface"}_{Guid.NewGuid():N}", TypeAttributes.Public | TypeAttributes.Class,
 2303                typeof(ActLikeProxy));
 304
 305
 306
 307
 8308            foreach (var tInterface in informalInterface)
 309            {
 310
 2311                MakePropertyDescribedProperty(builder, tB, contextType, tInterface.Key, tInterface.Value);
 312
 313            }
 2314            var tType = tB.CreateTypeInfo();
 2315            return tType;
 316        }
 317
 318        private void MakePropertyDescribedProperty(ModuleBuilder builder, TypeBuilder typeBuilder, Type contextType, str
 319        {
 320
 321
 2322            var tGetName = "get_" + tName;
 323
 2324            var tEmitInfo = new PropertyEmitInfo
 2325                { Name = tName, GetName = tGetName, DefaultInterfaceImplementation = true, ContextType = contextType, Re
 326
 327
 328
 329
 2330            MakePropertyHelper(builder, typeBuilder, tEmitInfo);
 2331        }
 332
 333        private static Type DefineCallsiteFieldForMethod(TypeBuilder builder, ActLikeMaker maker, string name, Type retu
 334        {
 587335            Type tFuncType = maker.GenerateCallSiteFuncType(argTypes, returnType, info, builder);
 587336            Type tReturnType = typeof(CallSite<>).MakeGenericType(tFuncType);
 337
 587338            builder.DefineField(name, tReturnType, FieldAttributes.Static | FieldAttributes.Public);
 587339            return tFuncType;
 340
 341        }
 342
 343
 344        internal static Type DefineCallsiteField(TypeBuilder builder, ActLikeMaker maker, string name, Type returnType, 
 345        {
 824346            Type tFuncType = maker.GenerateCallSiteFuncType(argTypes, returnType);
 824347            Type tReturnType = typeof(CallSite<>).MakeGenericType(tFuncType);
 348
 824349            builder.DefineField(name, tReturnType, FieldAttributes.Static | FieldAttributes.Public);
 824350            return tFuncType;
 351
 352        }
 353
 354        private class MethodSigHash
 355        {
 356            public readonly string Name;
 357            public readonly Type[] Parameters;
 358
 587359            public MethodSigHash(MethodInfo info)
 360            {
 587361                Name = info.Name;
 587362                Parameters = info.GetParameters().Select(it => it.ParameterType).ToArray();
 587363            }
 364
 0365            public MethodSigHash(string name, Type[] parameters)
 366            {
 0367                Name = name;
 0368                Parameters = parameters;
 0369            }
 370
 371            public bool Equals(MethodSigHash other)
 372            {
 6373                if (ReferenceEquals(null, other)) return false;
 6374                if (ReferenceEquals(this, other)) return true;
 6375                return Equals(other.Name, Name) && StructuralComparisons.StructuralEqualityComparer.Equals(other.Paramet
 376            }
 377
 378            public override bool Equals(object obj)
 379            {
 6380                if (ReferenceEquals(null, obj)) return false;
 6381                if (ReferenceEquals(this, obj)) return true;
 6382                if (obj.GetType() != typeof(MethodSigHash)) return false;
 6383                return Equals((MethodSigHash)obj);
 384            }
 385
 386            public override int GetHashCode()
 387            {
 388                unchecked
 389                {
 587390                    return (Name.GetHashCode() * 397) ^ StructuralComparisons.StructuralEqualityComparer.GetHashCode(Par
 391                }
 392            }
 393        }
 394
 395        private Type BuildTypeHelper(ModuleBuilder builder, Type contextType, params Type[] interfaces)
 396        {
 397
 71398            var tInterfacesMainList = interfaces.Distinct().ToArray();
 71399            var tB = builder.DefineType(
 71400                $"ActLike_{tInterfacesMainList.First().Name}_{Guid.NewGuid():N}", TypeAttributes.Public | TypeAttributes
 71401                typeof(ActLikeProxy), tInterfacesMainList);
 402
 71403            tB.SetCustomAttribute(
 71404                new CustomAttributeBuilder(typeof(ActLikeProxyAttribute).GetConstructor(new[] { typeof(Type).MakeArrayTy
 71405                    new object[] { interfaces, contextType }));
 71406            tB.SetCustomAttribute(new CustomAttributeBuilder(typeof(SerializableAttribute).GetConstructor(Type.EmptyType
 407
 408
 71409            var tInterfaces = tInterfacesMainList.Concat(tInterfacesMainList.SelectMany(it => it.GetInterfaces()));
 410
 411
 71412            var tPropertyNameHash = new HashSet<string>();
 71413            var tMethodHashSet = new HashSet<MethodSigHash>();
 414
 71415            object tAttr = null;
 330416            foreach (var tInterface in tInterfaces.Distinct())
 417            {
 418
 94419                if (tInterface != null && tAttr == null)
 420                {
 94421                    var tCustomAttributes = tInterface.GetCustomAttributesData();
 196422                    foreach (var tCustomAttribute in tCustomAttributes.Where(it => typeof(DefaultMemberAttribute).IsAssi
 423                    {
 424                        try
 425                        {
 4426                            tB.SetCustomAttribute(GetAttributeBuilder(tCustomAttribute));
 4427                        }
 0428                        catch
 429                        {
 0430                        } //For most proxies not having the same attributes won't really matter,
 431                        //but just incase we don't want to stop for some unknown attribute that we can't initialize
 432                    }
 433                }
 434
 435
 436
 437
 94438                var tNonRecursive = tInterface.GetCustomAttributes(typeof(NonRecursiveInterfaceAttribute), true).Any();
 439
 380440                foreach (var tInfo in tInterface.GetProperties(BindingFlags.Public | BindingFlags.Instance))
 441                {
 96442                    var tNonRecursiveProp = tNonRecursive ||
 96443                                            tInfo.GetCustomAttributes(typeof(NonRecursiveInterfaceAttribute), true).Any(
 444
 96445                    MakeProperty(builder, tInfo, tB, contextType, nonRecursive: tNonRecursiveProp, defaultImp: tProperty
 446                }
 1362447                foreach (var tInfo in tInterface.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(it => !it
 448                {
 587449                    var tNonRecursiveMeth = tNonRecursive ||
 587450                                            tInfo.GetCustomAttributes(typeof(NonRecursiveInterfaceAttribute), true).Any(
 587451                    MakeMethod(builder, tInfo, tB, contextType, nonRecursive: tNonRecursiveMeth, defaultImp: tMethodHash
 452                }
 198453                foreach (var tInfo in tInterface.GetEvents(BindingFlags.Public | BindingFlags.Instance).Where(it => !it.
 454                {
 5455                    MakeEvent(builder, tInfo, tB, contextType, defaultImp: tPropertyNameHash.Add(tInfo.Name));
 456                }
 457            }
 71458            var tType = tB.CreateTypeInfo();
 71459            return tType;
 460        }
 461
 462
 463        private IEnumerable<Type> FlattenGenericParameters(Type type)
 464        {
 2059465            if (type.IsByRef || type.IsArray || type.IsPointer)
 466            {
 8467                return FlattenGenericParameters(type.GetElementType());
 468            }
 469
 2051470            if (type.IsGenericParameter)
 827471                return new[] { type };
 1224472            if (type.ContainsGenericParameters)
 473            {
 266474                return type.GetGenericArguments().SelectMany(FlattenGenericParameters);
 475            }
 958476            return new Type[] { };
 477        }
 478
 479        private Type ReplaceTypeWithGenericBuilder(Type type, IDictionary<Type, GenericTypeParameterBuilder> dict)
 480        {
 2912481            var tStartType = type;
 482            Type tReturnType;
 2912483            if (type.IsByRef || type.IsArray || type.IsPointer)
 484            {
 3485                tStartType = type.GetElementType();
 486            }
 487
 488
 2912489            if (tStartType.IsGenericType)
 490            {
 1126491                var tArgs = tStartType.GetGenericArguments().Select(it => ReplaceTypeWithGenericBuilder(it, dict));
 492
 1126493                var tNewType = tStartType.GetGenericTypeDefinition().MakeGenericType(tArgs.ToArray());
 1126494                tReturnType = tNewType;
 495            }
 1786496            else if (dict.ContainsKey(tStartType))
 497            {
 1119498                var tNewType = dict[tStartType];
 1119499                var tAttributes = tStartType.GenericParameterAttributes;
 1119500                tNewType.SetGenericParameterAttributes(tAttributes);
 2246501                foreach (var tConstraint in tStartType.GetGenericParameterConstraints())
 502                {
 4503                    if (tConstraint.IsInterface)
 2504                        tNewType.SetInterfaceConstraints(tConstraint);
 505                    else
 2506                        tNewType.SetBaseTypeConstraint(tConstraint);
 507                }
 1119508                tReturnType = tNewType;
 509            }
 510            else
 511            {
 667512                tReturnType = tStartType;
 513            }
 514
 2912515            if (type.IsByRef)
 516            {
 3517                return tReturnType.MakeByRefType();
 518            }
 519
 2909520            if (type.IsArray)
 521            {
 0522                return tReturnType.MakeArrayType();
 523            }
 524
 2909525            if (type.IsPointer)
 526            {
 0527                return tReturnType.MakePointerType();
 528            }
 529
 2909530            return tReturnType;
 531        }
 532
 533        private object CustomAttributeTypeArgument(CustomAttributeTypedArgument argument)
 534        {
 6535            if (argument.Value is ReadOnlyCollection<CustomAttributeTypedArgument>)
 536            {
 2537                var tValue = argument.Value as ReadOnlyCollection<CustomAttributeTypedArgument>;
 2538                return
 2539                    new ArrayList(tValue.Select(it => it.Value).ToList()).ToArray(argument.ArgumentType.GetElementType()
 540            }
 541
 4542            return argument.Value;
 543        }
 544
 545
 1546        private static readonly Type[] FuncKinds =
 1547        {
 1548            typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), typeof(Func<,,,>), typeof(Func<,,,,>),
 1549            typeof(Func<,,,,,>), typeof(Func<,,,,,,>), typeof(Func<,,,,,,,>), typeof(Func<,,,,,,,,>),
 1550            typeof(Func<,,,,,,,,,>), typeof(Func<,,,,,,,,,,>), typeof(Func<,,,,,,,,,,,>),
 1551            typeof(Func<,,,,,,,,,,,,>), typeof(Func<,,,,,,,,,,,,,>), typeof(Func<,,,,,,,,,,,,,,>),
 1552            typeof(Func<,,,,,,,,,,,,,,,>), typeof(Func<,,,,,,,,,,,,,,,,>)
 1553        };
 554
 1555        private static readonly Type[] ActionKinds =
 1556        {
 1557            typeof(Action), typeof(Action<>), typeof(Action<,>), typeof(Action<,,>), typeof(Action<,,,>),
 1558            typeof(Action<,,,,>), typeof(Action<,,,,,>), typeof(Action<,,,,,,>), typeof(Action<,,,,,,,>),
 1559            typeof(Action<,,,,,,,,>), typeof(Action<,,,,,,,,,>), typeof(Action<,,,,,,,,,,>),
 1560            typeof(Action<,,,,,,,,,,,>), typeof(Action<,,,,,,,,,,,,>), typeof(Action<,,,,,,,,,,,,,>),
 1561            typeof(Action<,,,,,,,,,,,,,,>), typeof(Action<,,,,,,,,,,,,,,,>)
 1562        };
 563
 564        /// <summary>
 565        /// The open `Func`/`Action` of that shape. `paramCount` counts the return type for a
 566        /// `Func`, as the caller's list does.
 567        /// </summary>
 568        private static Type GenericDelegateType(int paramCount, bool returnVoid = false)
 569        {
 408570            var count = returnVoid ? paramCount : paramCount - 1;
 408571            if (count > 16)
 0572                throw new ArgumentException(
 0573                    $"{(returnVoid ? "Action" : "Func")} only handles at most {(returnVoid ? 16 : 17)} parameters",
 0574                    nameof(paramCount));
 408575            if (count < 0)
 0576                throw new ArgumentException(
 0577                    $"{(returnVoid ? "Action" : "Func")} must have at least {(returnVoid ? 0 : 1)} parameter(s)",
 0578                    nameof(paramCount));
 579
 408580            return returnVoid ? ActionKinds[count] : FuncKinds[count];
 581        }
 582
 583        private CustomAttributeBuilder GetAttributeBuilder(CustomAttributeData data)
 584        {
 13585            var tPropertyInfos = new List<PropertyInfo>();
 13586            var tPropertyValues = new List<object>();
 13587            var tFieldInfos = new List<FieldInfo>();
 13588            var tFieldValues = new List<object>();
 589
 13590            if (data.NamedArguments != null)
 591            {
 26592                foreach (var namedArg in data.NamedArguments)
 593                {
 0594                    var fi = namedArg.MemberInfo as FieldInfo;
 0595                    var pi = namedArg.MemberInfo as PropertyInfo;
 596
 0597                    if (fi != null)
 598                    {
 0599                        tFieldInfos.Add(fi);
 0600                        tFieldValues.Add(namedArg.TypedValue.Value);
 601                    }
 0602                    else if (pi != null)
 603                    {
 0604                        tPropertyInfos.Add(pi);
 0605                        tPropertyValues.Add(namedArg.TypedValue.Value);
 606                    }
 607                }
 608            }
 609
 13610            return new CustomAttributeBuilder(
 13611                data.Constructor,
 13612                data.ConstructorArguments.Select(CustomAttributeTypeArgument).ToArray(),
 13613                tPropertyInfos.ToArray(),
 13614                tPropertyValues.ToArray(),
 13615                tFieldInfos.ToArray(),
 13616                tFieldValues.ToArray());
 617        }
 618
 619
 620        private void MakeMethod(ModuleBuilder builder, MethodInfo info, TypeBuilder typeBuilder, Type contextType, bool 
 621        {
 622
 623
 587624            var tEmitInfo = new MethodEmitInfo { Name = info.Name, DefaultInterfaceImplementation = defaultImp, NonRecur
 625
 587626            if (info.GetCustomAttributes(typeof(AliasAttribute), false).FirstOrDefault() is AliasAttribute alias)
 627            {
 1628                tEmitInfo.Alias = alias.Name;
 629            }
 630
 587631            var tParamAttri = info.GetParameters();
 587632            Type[] tParamTypes = tParamAttri.Select(it => it.ParameterType).ToArray();
 633
 634
 635            IEnumerable<string> tArgNames;
 587636            if (info.GetCustomAttributes(typeof(UseNamedArgumentAttribute), false).Any() ||
 587637                info.DeclaringType.GetCustomAttributes(typeof(UseNamedArgumentAttribute), false).Any())
 638
 639            {
 1640                tArgNames = tParamAttri.Select(it => it.Name).ToList();
 641            }
 642            else
 643            {
 586644                var tParam = tParamAttri.Zip(Enumerable.Range(0, tParamTypes.Count()), (p, i) => new { i, p })
 586645                    .FirstOrDefault(it => it.p.GetCustomAttributes(typeof(UseNamedArgumentAttribute), false).Any());
 646
 586647                tArgNames = tParam == null
 586648                    ? Enumerable.Repeat(default(string), tParamTypes.Length)
 586649                    : Enumerable.Repeat(default(string), tParam.i).Concat(tParamAttri.Skip(Math.Min(tParam.i - 1, 0)).Se
 650            }
 651
 652
 587653            var tReturnType = typeof(void);
 587654            if (info.ReturnParameter != null)
 587655                tReturnType = info.ReturnParameter.ParameterType;
 656
 657
 587658            var tCallSiteName = tEmitInfo.CallSiteName;
 587659            var tCStp = DefineBuilderForCallSite(builder, tCallSiteName);
 660
 661
 662
 587663            var tReplacedTypes = GetParamTypes(tCStp, info);
 587664            if (tReplacedTypes != null)
 665            {
 159666                tReturnType = tReplacedTypes.Item1;
 159667                tParamTypes = tReplacedTypes.Item2;
 668            }
 669
 587670            var tConvert = tEmitInfo.CallSiteConvertName;
 587671            Type tConvertFuncType = null;
 587672            if (tReturnType != typeof(void))
 673            {
 569674                tConvertFuncType = DefineCallsiteField(tCStp, this, tConvert, tReturnType);
 675            }
 676
 587677            var tInvokeMethod = tEmitInfo.CallSiteInvokeName;
 587678            var tInvokeFuncType = DefineCallsiteFieldForMethod(tCStp, this, tInvokeMethod, tReturnType != typeof(void) ?
 679
 680
 681
 682
 587683            Type tCallSite = tCStp.CreateTypeInfo();
 684
 587685            var tPublicPrivate = MethodAttributes.Public;
 587686            var tPrefixName = tEmitInfo.Name;
 587687            if (!tEmitInfo.DefaultInterfaceImplementation)
 688            {
 6689                tPrefixName = String.Format("{0}.{1}", info.DeclaringType.FullName, tPrefixName);
 690
 6691                tPublicPrivate = MethodAttributes.Private;
 692            }
 693
 694
 587695            var tMethodBuilder = typeBuilder.DefineMethod(tPrefixName,
 587696                tPublicPrivate | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Final | Method
 697
 698
 699
 587700            tReplacedTypes = GetParamTypes(tMethodBuilder, info);
 587701            var tReducedParams = tParamTypes.Select(ReduceToElementType).ToArray();
 587702            if (tReplacedTypes != null)
 703            {
 159704                tReturnType = tReplacedTypes.Item1;
 159705                tParamTypes = tReplacedTypes.Item2;
 706
 159707                tReducedParams = tParamTypes.Select(ReduceToElementType).ToArray();
 159708                var tGenericParams = tMethodBuilder.GetGenericArguments();
 159709                tCallSite = tCallSite.GetGenericTypeDefinition().MakeGenericType(tGenericParams);
 159710                if (tConvertFuncType != null)
 159711                    tConvertFuncType = UpdateCallsiteFuncType(tConvertFuncType, tReturnType);
 159712                tInvokeFuncType = UpdateCallsiteFuncType(tInvokeFuncType, tReturnType != typeof(void) ? typeof(object) :
 713            }
 714
 587715            tMethodBuilder.SetReturnType(tReturnType);
 587716            tMethodBuilder.SetParameters(tParamTypes);
 717
 2548718            foreach (var tParam in info.GetParameters())
 719            {
 687720                var tParamBuilder = tMethodBuilder.DefineParameter(tParam.Position + 1, AttributesForParam(tParam), tPar
 721
 722
 687723                var tCustomAttributes = tParam.GetCustomAttributesData();
 1392724                foreach (var tCustomAttribute in tCustomAttributes)
 725                {
 726                    try
 727                    {
 9728                        tParamBuilder.SetCustomAttribute(GetAttributeBuilder(tCustomAttribute));
 9729                    }
 0730                    catch { }//For most proxies not having the same attributes won't really matter,
 731                    //but just incase we don't want to stop for some unknown attribute that we can't initialize
 732                }
 733
 734
 735            }
 736
 587737            if (!tEmitInfo.DefaultInterfaceImplementation)
 738            {
 6739                typeBuilder.DefineMethodOverride(tMethodBuilder, info);
 740            }
 587741            tEmitInfo.ResolvedParamTypes = tReducedParams;
 587742            tEmitInfo.ResolveReturnType = tReturnType;
 587743            tEmitInfo.CallSiteType = tCallSite;
 587744            tEmitInfo.ContextType = contextType;
 587745            tEmitInfo.CallSiteConvertFuncType = tConvertFuncType;
 587746            tEmitInfo.CallSiteInvokeFuncType = tInvokeFuncType;
 587747            tEmitInfo.ArgNames = tArgNames;
 587748            EmitMethodBody(tMethodBuilder, tParamAttri, tEmitInfo);
 587749        }
 750
 751        private TypeBuilder DefineBuilderForCallSite(ModuleBuilder builder, string tCallSiteInvokeName)
 752        {
 690753            return builder.DefineType(tCallSiteInvokeName,
 690754
 690755                TypeAttributes.NotPublic
 690756                | TypeAttributes.Sealed
 690757                | TypeAttributes.AutoClass
 690758                | TypeAttributes.BeforeFieldInit
 690759                | TypeAttributes.Abstract
 690760            );
 761        }
 762
 763        private Tuple<Type, Type[]> GetParamTypes(dynamic builder, MethodInfo info)
 764        {
 1178765            if (info == null)
 0766                return null;
 767
 768
 1178769            var paramTypes = info.GetParameters().Select(it => it.ParameterType).ToArray();
 1178770            var returnType = typeof(void);
 1178771            if (info.ReturnParameter != null)
 1178772                returnType = info.ReturnParameter.ParameterType;
 773
 1178774            var tGenericParams = info.GetGenericArguments()
 1178775                .SelectMany(FlattenGenericParameters)
 1178776                .Distinct().ToDictionary(it => it.GenericParameterPosition, it => new { Type = it, Gen = default(Generic
 1178777            var tParams = tGenericParams;
 1178778            var tReturnParameters = FlattenGenericParameters(returnType).Where(it => !tParams.ContainsKey(it.GenericPara
 2356779            foreach (var tReParm in tReturnParameters)
 0780                tGenericParams.Add(tReParm.GenericParameterPosition, new { Type = tReParm, Gen = default(GenericTypePara
 1178781            var tGenParams = tGenericParams.OrderBy(it => it.Key).Select(it => it.Value.Type.Name);
 1178782            if (tGenParams.Any())
 783            {
 319784                GenericTypeParameterBuilder[] tBuilders = builder.DefineGenericParameters(tGenParams.ToArray());
 319785                var tDict = tGenericParams.ToDictionary(param => param.Value.Type, param => tBuilders[param.Key]);
 786
 319787                returnType = ReplaceTypeWithGenericBuilder(returnType, tDict);
 319788                if (tDict.ContainsKey(returnType))
 789                {
 0790                    returnType = tDict[returnType];
 791                }
 319792                paramTypes = paramTypes.Select(it => ReplaceTypeWithGenericBuilder(it, tDict)).ToArray();
 319793                return Tuple.Create(returnType, paramTypes);
 794            }
 859795            return null;
 796        }
 797
 798
 799
 800
 801        private void EmitMethodBody(
 802            MethodBuilder methodBuilder,
 803            ParameterInfo[] paramInfo,
 804            MethodEmitInfo emitInfo
 805        )
 806        {
 587807            var tIlGen = methodBuilder.GetILGenerator();
 808
 587809            var tConvertField = emitInfo.CallSiteType.GetFieldEvenIfGeneric(emitInfo.CallSiteConvertName);
 587810            if (emitInfo.ResolveReturnType != typeof(void))
 811            {
 812
 813
 569814                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tConvertField)))
 815                {
 569816                    tIlGen.EmitDynamicConvertBinder(CSharpBinderFlags.None, emitInfo.ResolveReturnType, emitInfo.Context
 569817                    tIlGen.EmitCallsiteCreate(emitInfo.CallSiteConvertFuncType);
 569818                    tIlGen.Emit(OpCodes.Stsfld, tConvertField);
 569819                }
 820            }
 821
 587822            var tInvokeField = emitInfo.CallSiteType.GetFieldEvenIfGeneric(emitInfo.CallSiteInvokeName);
 823
 587824            using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tInvokeField)))
 825            {
 587826                tIlGen.EmitDynamicMethodInvokeBinder(
 587827                    emitInfo.ResolveReturnType == typeof(void) ? CSharpBinderFlags.ResultDiscarded : CSharpBinderFlags.N
 587828                    emitInfo.Alias ?? emitInfo.Name,
 587829                    methodBuilder.GetGenericArguments(),
 587830                    emitInfo.ContextType,
 587831                    paramInfo,
 587832                    emitInfo.ArgNames);
 587833                tIlGen.EmitCallsiteCreate(emitInfo.CallSiteInvokeFuncType);
 587834                tIlGen.Emit(OpCodes.Stsfld, tInvokeField);
 587835            }
 836
 837            //If it's an interface and not nonrecursive this will be true
 587838            var tRecurse = emitInfo.ResolveReturnType.IsInterface && !emitInfo.NonRecursive;
 839
 587840            if (emitInfo.ResolveReturnType != typeof(void) && !tRecurse)
 841            {
 348842                tIlGen.Emit(OpCodes.Ldsfld, tConvertField);
 348843                tIlGen.Emit(OpCodes.Ldfld, typeof(CallSite<>).MakeGenericType(emitInfo.CallSiteConvertFuncType).GetField
 348844                tIlGen.Emit(OpCodes.Ldsfld, tConvertField);
 845            }
 846
 587847            tIlGen.Emit(OpCodes.Ldsfld, tInvokeField);
 587848            tIlGen.Emit(OpCodes.Ldfld, typeof(CallSite<>).MakeGenericType(emitInfo.CallSiteInvokeFuncType).GetFieldEvenI
 587849            tIlGen.Emit(OpCodes.Ldsfld, tInvokeField);
 587850            tIlGen.Emit(OpCodes.Ldarg_0);
 587851            tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Original)).GetGetMethod
 2548852            for (var i = 1; i <= emitInfo.ResolvedParamTypes.Length; i++)
 853            {
 854
 687855                tIlGen.EmitLoadArgument(i);
 856            }
 587857            tIlGen.EmitCallInvokeFunc(emitInfo.CallSiteInvokeFuncType);
 587858            if (emitInfo.ResolveReturnType != typeof(void) && !tRecurse)
 859            {
 348860                tIlGen.EmitCallInvokeFunc(emitInfo.CallSiteConvertFuncType);
 861            }
 862
 863            //If we are recursing, try actlike
 587864            if (tRecurse)
 865            {
 221866                var tReturnLocal = tIlGen.DeclareLocal(typeof(object));
 221867                tIlGen.EmitStoreLocation(tReturnLocal.LocalIndex);
 221868                using (tIlGen.EmitBranchFalse(gen => gen.EmitLoadLocation(tReturnLocal.LocalIndex)))
 869                {
 221870                    tIlGen.EmitLoadLocation(tReturnLocal.LocalIndex);
 221871                    using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Isinst, emitInfo.ResolveReturnType)))
 872                    {
 221873                        tIlGen.Emit(OpCodes.Ldarg_0);
 221874                        tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Maker)).Get
 221875                        tIlGen.EmitLoadLocation(tReturnLocal.LocalIndex);
 221876                        tIlGen.Emit(OpCodes.Call, ActLikeRec.MakeGenericMethod(emitInfo.ResolveReturnType));
 221877                        tIlGen.Emit(OpCodes.Ret);
 221878                    }
 879                }
 880
 221881                tIlGen.Emit(OpCodes.Ldsfld, tConvertField);
 221882                tIlGen.Emit(OpCodes.Ldfld, typeof(CallSite<>).MakeGenericType(emitInfo.CallSiteConvertFuncType).GetField
 221883                tIlGen.Emit(OpCodes.Ldsfld, tConvertField);
 221884                tIlGen.EmitLoadLocation(tReturnLocal.LocalIndex);
 221885                tIlGen.EmitCallInvokeFunc(emitInfo.CallSiteConvertFuncType);
 886            }
 887
 888
 587889            tIlGen.Emit(OpCodes.Ret);
 587890        }
 891
 892
 893        private void MakeProperty(ModuleBuilder builder, PropertyInfo info, TypeBuilder typeBuilder, Type contextType, b
 894        {
 96895            var tEmitInfo = new PropertyEmitInfo()
 96896            {
 96897                Name = info.Name,
 96898                ResolveReturnType = info.PropertyType,
 96899                GetName = info.CanRead ? info.GetGetMethod().Name : null, // q: getter may be missing!
 96900                SetName = info.CanWrite ? info.GetSetMethod().Name : null, // q: setter may be missing!
 96901                ContextType = contextType,
 96902                DefaultInterfaceImplementation = defaultImp,
 96903                NonRecursive = nonRecursive
 96904            };
 905
 96906            if (info.GetCustomAttributes(typeof(AliasAttribute), false).FirstOrDefault() is AliasAttribute alias)
 907            {
 1908                tEmitInfo.Alias = alias.Name;
 909            }
 910
 96911            MakePropertyHelper(builder, typeBuilder, tEmitInfo, info);
 96912        }
 913
 914        private class PropertyEmitInfo : EmitInfo
 915        {
 103916            public PropertyEmitInfo()
 917            {
 103918                CallSiteConvertName = "Convert_Get";
 103919                CallSiteInvokeGetName = "Invoke_Get";
 103920                CallSiteInvokeSetName = "Invoke_Set";
 921
 103922            }
 923            public string GetName { get; set; }
 924            public string SetName { get; set; }
 925
 926            public string CallSiteInvokeSetName { get; protected set; }
 927            public string CallSiteInvokeGetName { get; protected set; }
 928            public string CallSiteConvertName { get; protected set; }
 929
 930            public Type[] ResolvedIndexParamTypes { get; set; }
 931            public Type CallSiteConvertFuncType { get; set; }
 932            public Type CallSiteInvokeGetFuncType { get; set; }
 933            public Type CallSiteInvokeSetFuncType { get; set; }
 934        }
 935
 936        private class EmitEventInfo : PropertyEmitInfo
 937        {
 938            public string CallSiteIsEventName { get; protected set; }
 939            public string CallSiteAddAssignName { get; protected set; }
 940            public string CallSiteSubtractAssignName { get; protected set; }
 941            public string CallSiteAddName { get; protected set; }
 942            public string CallSiteRemoveName { get; protected set; }
 943
 944
 945            public Type CallSiteIsEventFuncType { get; set; }
 946            public Type CallSiteAddAssignFuncType { get; set; }
 947            public Type CallSiteSubtractAssignFuncType { get; set; }
 948            public Type CallSiteAddFuncType { get; set; }
 949            public Type CallSiteRemoveFuncType { get; set; }
 950            public Type[] ResolvedAddParamTypes { get; set; }
 951            public Type[] ResolvedRemoveParamTypes { get; set; }
 952
 5953            public EmitEventInfo()
 954            {
 5955                CallSiteIsEventName = "Invoke_IsEvent";
 5956                CallSiteAddAssignName = "Invoke_AddAssign";
 5957                CallSiteSubtractAssignName = "Invoke_SubtractAssign";
 5958                CallSiteAddName = "Invoke_Add";
 5959                CallSiteRemoveName = "Invoke_Remove";
 5960            }
 961        }
 962
 963        private void MakeEvent(ModuleBuilder builder, EventInfo info, TypeBuilder typeBuilder, Type contextType, bool de
 964        {
 5965            var tEmitInfo = new EmitEventInfo
 5966            {
 5967                Name = info.Name,
 5968                ContextType = contextType,
 5969                DefaultInterfaceImplementation = defaultImp
 5970            };
 5971            if (info.GetCustomAttributes(typeof(AliasAttribute), false).FirstOrDefault() is AliasAttribute alias)
 972            {
 1973                tEmitInfo.Alias = alias.Name;
 974            }
 975
 5976            var tAddMethod = info.GetAddMethod();
 5977            var tRemoveMethod = info.GetRemoveMethod();
 5978            tEmitInfo.ResolveReturnType = info.EventHandlerType;
 979
 980
 5981            var tCStp = DefineBuilderForCallSite(builder, tEmitInfo.CallSiteName);
 982
 983
 5984            tEmitInfo.CallSiteIsEventFuncType = DefineCallsiteField(tCStp, this, tEmitInfo.CallSiteIsEventName, typeof(b
 985
 986
 5987            tEmitInfo.CallSiteAddAssignFuncType = DefineCallsiteField(tCStp, this, tEmitInfo.CallSiteAddAssignName, type
 988
 5989            tEmitInfo.CallSiteSubtractAssignFuncType = DefineCallsiteField(tCStp, this, tEmitInfo.CallSiteSubtractAssign
 990
 5991            tEmitInfo.ResolvedAddParamTypes = tRemoveMethod.GetParameters().Select(it => it.ParameterType).ToArray();
 5992            tEmitInfo.CallSiteAddFuncType = DefineCallsiteField(tCStp, this, tEmitInfo.CallSiteAddName, typeof(object), 
 993
 5994            tEmitInfo.ResolvedRemoveParamTypes = tRemoveMethod.GetParameters().Select(it => it.ParameterType).ToArray();
 5995            tEmitInfo.CallSiteRemoveFuncType = DefineCallsiteField(tCStp, this, tEmitInfo.CallSiteRemoveName, typeof(obj
 996
 5997            tEmitInfo.CallSiteInvokeGetFuncType = DefineCallsiteField(tCStp, this, tEmitInfo.CallSiteInvokeGetName, type
 998
 5999            tEmitInfo.CallSiteInvokeSetFuncType = DefineCallsiteField(tCStp, this, tEmitInfo.CallSiteInvokeSetName, type
 1000
 51001            tEmitInfo.CallSiteType = tCStp.CreateTypeInfo();
 1002
 51003            var tMp = typeBuilder.DefineEvent(info.Name, EventAttributes.None, tEmitInfo.ResolveReturnType);
 1004
 1005
 51006            var tSetField = tEmitInfo.CallSiteType.GetFieldEvenIfGeneric(tEmitInfo.CallSiteInvokeSetName);
 51007            var tGetField = tEmitInfo.CallSiteType.GetFieldEvenIfGeneric(tEmitInfo.CallSiteInvokeGetName);
 51008            var tIsEventField = tEmitInfo.CallSiteType.GetFieldEvenIfGeneric(tEmitInfo.CallSiteIsEventName);
 1009
 51010            var tPublicPrivate = MethodAttributes.Public;
 51011            if (!tEmitInfo.DefaultInterfaceImplementation)
 1012            {
 11013                tPublicPrivate = MethodAttributes.Private;
 1014            }
 1015
 1016            //AddMethod
 51017            var tAddPrefixName = tAddMethod.Name;
 51018            if (!tEmitInfo.DefaultInterfaceImplementation)
 1019            {
 11020                tAddPrefixName = $"{info.DeclaringType.FullName}.{tAddPrefixName}";
 1021            }
 1022
 51023            var tAddBuilder = typeBuilder.DefineMethod(tAddPrefixName,
 51024                tPublicPrivate | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual | 
 51025                typeof(void),
 51026                tEmitInfo.ResolvedAddParamTypes);
 1027
 51028            if (!tEmitInfo.DefaultInterfaceImplementation)
 1029            {
 11030                typeBuilder.DefineMethodOverride(tAddBuilder, info.GetAddMethod());
 1031            }
 1032
 201033            foreach (var tParam in tAddMethod.GetParameters())
 1034            {
 51035                tAddBuilder.DefineParameter(tParam.Position + 1, AttributesForParam(tParam), tParam.Name);
 1036            }
 1037
 51038            EmitAddEvent(tMp, tAddBuilder, info, tAddMethod, tGetField, tSetField, tIsEventField, tEmitInfo);
 1039
 1040            //Remove Method
 51041            var tRemovePrefixName = tRemoveMethod.Name;
 51042            if (!tEmitInfo.DefaultInterfaceImplementation)
 1043            {
 11044                tRemovePrefixName = $"{info.DeclaringType.FullName}.{tRemovePrefixName}";
 1045
 1046            }
 51047            var tRemoveBuilder = typeBuilder.DefineMethod(tRemovePrefixName,
 51048                tPublicPrivate
 51049                | MethodAttributes.SpecialName
 51050                | MethodAttributes.HideBySig
 51051                | MethodAttributes.Virtual
 51052                | MethodAttributes.Final
 51053                | MethodAttributes.NewSlot,
 51054                typeof(void),
 51055                tEmitInfo.ResolvedAddParamTypes);
 51056            if (!tEmitInfo.DefaultInterfaceImplementation)
 1057            {
 11058                typeBuilder.DefineMethodOverride(tRemoveBuilder, info.GetRemoveMethod());
 1059            }
 1060
 201061            foreach (var tParam in tRemoveMethod.GetParameters())
 1062            {
 51063                tRemoveBuilder.DefineParameter(tParam.Position + 1, AttributesForParam(tParam), tParam.Name);
 1064            }
 1065
 1066
 51067            EmitRemoveEvent(tMp, tRemoveBuilder, info, tRemoveMethod, tGetField, tSetField, tIsEventField, tEmitInfo);
 51068        }
 1069
 1070        private void EmitRemoveEvent(EventBuilder tMp, MethodBuilder tRemoveBuilder, EventInfo info, MethodInfo tRemoveM
 1071            FieldInfo tGetField, FieldInfo tSetField, FieldInfo tIsEventField,
 1072            EmitEventInfo tEmitInfo)
 1073        {
 51074            var tIlGen = tRemoveBuilder.GetILGenerator();
 1075
 1076
 51077            using (tIlGen.EmitBranchTrue(load => load.Emit(OpCodes.Ldsfld, tIsEventField)))
 1078            {
 51079                tIlGen.EmitDynamicIsEventBinder(CSharpBinderFlags.None, tEmitInfo.Alias ?? tEmitInfo.Name, tEmitInfo.Con
 51080                tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteIsEventFuncType);
 51081                tIlGen.Emit(OpCodes.Stsfld, tIsEventField);
 51082            }
 1083
 51084            using (tIlGen.EmitBranchTrue(
 51085                       load => load.EmitInvocation(
 51086                           target => target.EmitInvocation(
 51087                               t => t.Emit(OpCodes.Ldsfld, tIsEventField),
 51088                               i => i.Emit(OpCodes.Ldfld, tIsEventField.FieldType.GetFieldEvenIfGeneric("Target"))
 51089                           ),
 51090                           invoke => invoke.EmitCallInvokeFunc(tEmitInfo.CallSiteIsEventFuncType),
 51091                           param => param.Emit(OpCodes.Ldsfld, tIsEventField),
 51092                           param => param.EmitInvocation(
 51093                               t => t.Emit(OpCodes.Ldarg_0),
 51094                               i => i.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty("Original").GetGetMethod(
 51095                           )
 51096                       )
 51097                   )
 51098                  ) //if IsEvent Not True
 1099            {
 51100                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tSetField)))
 1101                {
 51102                    tIlGen.EmitDynamicSetBinderDynamicParams(CSharpBinderFlags.ValueFromCompoundAssignment, tEmitInfo.Al
 51103                        tEmitInfo.ContextType, tEmitInfo.ResolveReturnType);
 51104                    tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteInvokeSetFuncType);
 51105                    tIlGen.Emit(OpCodes.Stsfld, tSetField);
 51106                }
 1107
 51108                var tSubrtractAssignField = tEmitInfo.CallSiteType.GetFieldEvenIfGeneric(tEmitInfo.CallSiteSubtractAssig
 1109
 51110                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tSubrtractAssignField)))
 1111                {
 51112                    tIlGen.EmitDynamicBinaryOpBinder(CSharpBinderFlags.None, ExpressionType.SubtractAssign,
 51113                        tEmitInfo.ContextType, tEmitInfo.ResolveReturnType);
 51114                    tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteSubtractAssignFuncType);
 51115                    tIlGen.Emit(OpCodes.Stsfld, tSubrtractAssignField);
 51116                }
 1117
 1118
 51119                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tGetField)))
 1120                {
 51121                    tIlGen.EmitDynamicGetBinder(CSharpBinderFlags.None, tEmitInfo.Alias ?? tEmitInfo.Name, tEmitInfo.Con
 51122                    tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteInvokeGetFuncType);
 51123                    tIlGen.Emit(OpCodes.Stsfld, tGetField);
 51124                }
 1125
 51126                tIlGen.Emit(OpCodes.Ldsfld, tSetField);
 51127                tIlGen.Emit(OpCodes.Ldfld, tSetField.FieldType.GetFieldEvenIfGeneric("Target"));
 51128                tIlGen.Emit(OpCodes.Ldsfld, tSetField);
 51129                tIlGen.Emit(OpCodes.Ldarg_0);
 51130                tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Original)).GetGetMe
 1131
 51132                tIlGen.Emit(OpCodes.Ldsfld, tSubrtractAssignField);
 51133                tIlGen.Emit(OpCodes.Ldfld, tSubrtractAssignField.FieldType.GetFieldEvenIfGeneric("Target"));
 51134                tIlGen.Emit(OpCodes.Ldsfld, tSubrtractAssignField);
 1135
 51136                tIlGen.Emit(OpCodes.Ldsfld, tGetField);
 51137                tIlGen.Emit(OpCodes.Ldfld, tGetField.FieldType.GetFieldEvenIfGeneric("Target"));
 51138                tIlGen.Emit(OpCodes.Ldsfld, tGetField);
 51139                tIlGen.Emit(OpCodes.Ldarg_0);
 51140                tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Original)).GetGetMe
 1141
 51142                tIlGen.EmitCallInvokeFunc(tEmitInfo.CallSiteInvokeGetFuncType);
 1143
 51144                tIlGen.Emit(OpCodes.Ldarg_1);
 51145                tIlGen.EmitCallInvokeFunc(tEmitInfo.CallSiteSubtractAssignFuncType);
 1146
 51147                tIlGen.EmitCallInvokeFunc(tEmitInfo.CallSiteInvokeSetFuncType);
 1148
 51149                tIlGen.Emit(OpCodes.Pop);
 51150                tIlGen.Emit(OpCodes.Ret);
 51151            }
 1152
 51153            var tRemoveCallSiteField = tEmitInfo.CallSiteType.GetFieldEvenIfGeneric(tEmitInfo.CallSiteRemoveName);
 51154            using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tRemoveCallSiteField)))
 1155            {
 51156                tIlGen.EmitDynamicMethodInvokeBinder(
 51157                    CSharpBinderFlags.InvokeSpecialName | CSharpBinderFlags.ResultDiscarded,
 51158                    tEmitInfo.Alias == null ? tRemoveMethod.Name : $"remove_{tEmitInfo.Alias}",
 51159                    Enumerable.Empty<Type>(),
 51160                    tEmitInfo.ContextType,
 51161                    tRemoveMethod.GetParameters(),
 51162                    Enumerable.Repeat(default(string),
 51163                        tEmitInfo.ResolvedRemoveParamTypes.Length));
 51164                tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteRemoveFuncType);
 51165                tIlGen.Emit(OpCodes.Stsfld, tRemoveCallSiteField);
 51166            }
 51167            tIlGen.Emit(OpCodes.Ldsfld, tRemoveCallSiteField);
 51168            tIlGen.Emit(OpCodes.Ldfld, tRemoveCallSiteField.FieldType.GetFieldEvenIfGeneric("Target"));
 51169            tIlGen.Emit(OpCodes.Ldsfld, tRemoveCallSiteField);
 51170            tIlGen.Emit(OpCodes.Ldarg_0);
 51171            tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Original)).GetGetMethod
 51172            tIlGen.Emit(OpCodes.Ldarg_1);
 51173            tIlGen.EmitCallInvokeFunc(tEmitInfo.CallSiteRemoveFuncType);
 51174            tIlGen.Emit(OpCodes.Pop);
 51175            tIlGen.Emit(OpCodes.Ret);
 1176
 51177            tMp.SetRemoveOnMethod(tRemoveBuilder);
 51178        }
 1179
 1180        private void EmitAddEvent(EventBuilder tMp, MethodBuilder tAddBuilder, EventInfo info, MethodInfo tAddMethod,
 1181            FieldInfo tGetField, FieldInfo tSetField, FieldInfo tIsEventField, EmitEventInfo tEmitInfo)
 1182        {
 51183            var tIlGen = tAddBuilder.GetILGenerator();
 1184
 1185
 1186
 51187            using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tIsEventField)))
 1188            {
 51189                tIlGen.EmitDynamicIsEventBinder(CSharpBinderFlags.None, tEmitInfo.Alias ?? tEmitInfo.Name, tEmitInfo.Con
 51190                tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteIsEventFuncType);
 51191                tIlGen.Emit(OpCodes.Stsfld, tIsEventField);
 51192            }
 1193
 1194
 1195
 51196            using (tIlGen.EmitBranchTrue(
 51197                       load => load.EmitInvocation(
 51198                           target => target.EmitInvocation(
 51199                               t => t.Emit(OpCodes.Ldsfld, tIsEventField),
 51200                               i => i.Emit(OpCodes.Ldfld, tIsEventField.FieldType.GetFieldEvenIfGeneric("Target"))
 51201                           ),
 51202                           invoke => invoke.EmitCallInvokeFunc(tEmitInfo.CallSiteIsEventFuncType),
 51203                           param => param.Emit(OpCodes.Ldsfld, tIsEventField),
 51204                           param => param.EmitInvocation(
 51205                               t => t.Emit(OpCodes.Ldarg_0),
 51206                               i => i.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Orig
 51207                           )
 51208                       )
 51209                   )
 51210                  ) //if IsEvent Not True
 1211            {
 51212                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tSetField)))
 1213                {
 51214                    tIlGen.EmitDynamicSetBinderDynamicParams(CSharpBinderFlags.ValueFromCompoundAssignment, tEmitInfo.Al
 51215                        tEmitInfo.ContextType, typeof(Object));
 51216                    tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteInvokeSetFuncType);
 51217                    tIlGen.Emit(OpCodes.Stsfld, tSetField);
 51218                }
 1219
 51220                var tAddAssigneField = tEmitInfo.CallSiteType.GetFieldEvenIfGeneric(tEmitInfo.CallSiteAddAssignName);
 1221
 51222                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tAddAssigneField)))
 1223                {
 51224                    tIlGen.EmitDynamicBinaryOpBinder(CSharpBinderFlags.None, ExpressionType.AddAssign, tEmitInfo.Context
 51225                        tEmitInfo.ResolveReturnType);
 51226                    tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteAddAssignFuncType);
 51227                    tIlGen.Emit(OpCodes.Stsfld, tAddAssigneField);
 51228                }
 1229
 51230                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tGetField)))
 1231                {
 51232                    tIlGen.EmitDynamicGetBinder(CSharpBinderFlags.None, tEmitInfo.Alias ?? tEmitInfo.Name, tEmitInfo.Con
 51233                    tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteInvokeGetFuncType);
 51234                    tIlGen.Emit(OpCodes.Stsfld, tGetField);
 51235                }
 1236
 1237
 51238                tIlGen.Emit(OpCodes.Ldsfld, tSetField);
 51239                tIlGen.Emit(OpCodes.Ldfld, tSetField.FieldType.GetFieldEvenIfGeneric("Target"));
 51240                tIlGen.Emit(OpCodes.Ldsfld, tSetField);
 51241                tIlGen.Emit(OpCodes.Ldarg_0);
 51242                tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Original)).GetGetMe
 1243
 51244                tIlGen.Emit(OpCodes.Ldsfld, tAddAssigneField);
 51245                tIlGen.Emit(OpCodes.Ldfld, tAddAssigneField.FieldType.GetFieldEvenIfGeneric("Target"));
 51246                tIlGen.Emit(OpCodes.Ldsfld, tAddAssigneField);
 1247
 51248                tIlGen.Emit(OpCodes.Ldsfld, tGetField);
 51249                tIlGen.Emit(OpCodes.Ldfld, tGetField.FieldType.GetFieldEvenIfGeneric("Target"));
 51250                tIlGen.Emit(OpCodes.Ldsfld, tGetField);
 51251                tIlGen.Emit(OpCodes.Ldarg_0);
 51252                tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Original)).GetGetMe
 1253
 51254                tIlGen.EmitCallInvokeFunc(tEmitInfo.CallSiteInvokeGetFuncType);
 1255
 51256                tIlGen.Emit(OpCodes.Ldarg_1);
 51257                tIlGen.EmitCallInvokeFunc(tEmitInfo.CallSiteAddAssignFuncType);
 1258
 51259                tIlGen.EmitCallInvokeFunc(tEmitInfo.CallSiteInvokeSetFuncType);
 51260                tIlGen.Emit(OpCodes.Pop);
 51261                tIlGen.Emit(OpCodes.Ret);
 51262            }
 1263
 51264            var tAddCallSiteField = tEmitInfo.CallSiteType.GetFieldEvenIfGeneric(tEmitInfo.CallSiteAddName);
 1265
 51266            using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tAddCallSiteField)))
 1267            {
 51268                tIlGen.EmitDynamicMethodInvokeBinder(
 51269                    CSharpBinderFlags.InvokeSpecialName | CSharpBinderFlags.ResultDiscarded,
 51270                    tEmitInfo.Alias == null ? tAddMethod.Name : "add_" + tEmitInfo.Alias,
 51271                    Enumerable.Empty<Type>(),
 51272                    tEmitInfo.ContextType,
 51273                    tAddMethod.GetParameters(),
 51274                    Enumerable.Repeat(default(string),
 51275                        tEmitInfo.ResolvedAddParamTypes.Length));
 51276                tIlGen.EmitCallsiteCreate(tEmitInfo.CallSiteAddFuncType);
 51277                tIlGen.Emit(OpCodes.Stsfld, tAddCallSiteField);
 51278            }
 51279            tIlGen.Emit(OpCodes.Ldsfld, tAddCallSiteField);
 51280            tIlGen.Emit(OpCodes.Ldfld, tAddCallSiteField.FieldType.GetFieldEvenIfGeneric("Target"));
 51281            tIlGen.Emit(OpCodes.Ldsfld, tAddCallSiteField);
 51282            tIlGen.Emit(OpCodes.Ldarg_0);
 51283            tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Original)).GetGetMethod
 201284            for (var i = 1; i <= tEmitInfo.ResolvedAddParamTypes.Length; i++)
 1285            {
 51286                tIlGen.EmitLoadArgument(i);
 1287            }
 51288            tIlGen.EmitCallInvokeFunc(tEmitInfo.CallSiteAddFuncType);
 51289            tIlGen.Emit(OpCodes.Pop);
 51290            tIlGen.Emit(OpCodes.Ret);
 1291
 51292            tMp.SetAddOnMethod(tAddBuilder);
 1293
 51294        }
 1295
 1296
 1297        /// <summary>
 1298        /// Makes the property helper.
 1299        /// </summary>
 1300        /// <param name="builder">The builder.</param>
 1301        /// <param name="typeBuilder">The type builder.</param>
 1302        /// <param name="info">The info.</param>
 1303        /// <param name="emitInfo">The emit info.</param>
 1304        private void MakePropertyHelper(ModuleBuilder builder, TypeBuilder typeBuilder, PropertyEmitInfo emitInfo, Prope
 1305        {
 1306
 1307
 981308            emitInfo.ResolvedIndexParamTypes = new Type[] { };
 981309            if (info != null)
 1310            {
 961311                emitInfo.ResolvedIndexParamTypes = Enumerable.Select(info.GetIndexParameters(), it => it.ParameterType).
 1312            }
 1313
 1314
 981315            var tCallSiteInvokeName = emitInfo.CallSiteName;
 981316            var tCStp = DefineBuilderForCallSite(builder, tCallSiteInvokeName);
 1317
 1318
 981319            var tConvertGet = emitInfo.CallSiteConvertName;
 1320
 981321            emitInfo.CallSiteConvertFuncType = DefineCallsiteField(tCStp, this, tConvertGet, emitInfo.ResolveReturnType)
 1322
 981323            var tInvokeGet = emitInfo.CallSiteInvokeGetName;
 981324            if (info == null || info.CanRead)
 1325            {
 921326                emitInfo.CallSiteInvokeGetFuncType = DefineCallsiteField(tCStp, this, tInvokeGet, typeof(object), emitIn
 1327            }
 1328
 981329            var tInvokeSet = emitInfo.CallSiteInvokeSetName;
 981330            if (info != null && info.CanWrite)
 1331            {
 301332                emitInfo.ResolvedParamTypes = info.GetSetMethod().GetParameters().Select(it => it.ParameterType).ToArray
 1333
 301334                emitInfo.CallSiteInvokeSetFuncType = DefineCallsiteField(tCStp, this, tInvokeSet, typeof(object), emitIn
 1335            }
 1336
 981337            emitInfo.CallSiteType = tCStp.CreateTypeInfo();
 1338
 1339
 1340
 981341            var tPublicPrivate = MethodAttributes.Public;
 981342            var tPrefixedGet = emitInfo.GetName;
 981343            var tPrefixedSet = emitInfo.SetName;
 981344            var tPrefixedName = emitInfo.Name;
 981345            if (!emitInfo.DefaultInterfaceImplementation)
 1346            {
 31347                tPublicPrivate = MethodAttributes.Private;
 31348                tPrefixedGet = $"{info.DeclaringType.FullName}.{tPrefixedGet}";
 31349                tPrefixedSet = $"{info.DeclaringType.FullName}.{tPrefixedSet}";
 31350                tPrefixedName = $"{info.DeclaringType.FullName}.{tPrefixedName}";
 1351            }
 1352
 1353
 981354            var tMp = typeBuilder.DefineProperty(tPrefixedName, PropertyAttributes.None,
 981355
 981356                CallingConventions.HasThis,
 981357
 981358                emitInfo.ResolveReturnType, emitInfo.ResolvedIndexParamTypes);
 1359
 1360
 981361            MethodBuilder tGetMethodBuilder = null;
 981362            if (info == null || info.CanRead) // q: some props just don't have GET
 1363            {
 1364                //GetMethod
 921365                tGetMethodBuilder = typeBuilder.DefineMethod(tPrefixedGet,
 921366                    tPublicPrivate
 921367                    | MethodAttributes.SpecialName
 921368                    | MethodAttributes.HideBySig
 921369                    | MethodAttributes.Virtual
 921370                    | MethodAttributes.Final
 921371                    | MethodAttributes.NewSlot,
 921372                    emitInfo.ResolveReturnType,
 921373                    emitInfo.ResolvedIndexParamTypes);
 1374
 1375
 921376                if (!emitInfo.DefaultInterfaceImplementation)
 1377                {
 31378                    typeBuilder.DefineMethodOverride(tGetMethodBuilder, info.GetGetMethod());
 1379                }
 1380
 1381
 921382                if (info != null && info.GetGetMethod() != null)
 1383                {
 1881384                    foreach (var tParam in info.GetGetMethod().GetParameters())
 1385                    {
 41386                        tGetMethodBuilder.DefineParameter(tParam.Position + 1, AttributesForParam(tParam), tParam.Name);
 1387                    }
 1388                }
 1389            }
 1390
 981391            MethodBuilder tSetMethodBuilder = null;
 981392            if (info != null && info.CanWrite) // q: some props just don't have SET
 1393            {
 1394                //SetMethod
 301395                tSetMethodBuilder = typeBuilder.DefineMethod(tPrefixedSet,
 301396                    tPublicPrivate
 301397                    | MethodAttributes.SpecialName
 301398                    | MethodAttributes.HideBySig
 301399                    | MethodAttributes.Virtual
 301400                    | MethodAttributes.Final
 301401                    | MethodAttributes.NewSlot,
 301402                    null,
 301403                    emitInfo.ResolvedParamTypes);
 1404
 301405                if (!emitInfo.DefaultInterfaceImplementation)
 1406                {
 11407                    typeBuilder.DefineMethodOverride(tSetMethodBuilder, info.GetSetMethod());
 1408                }
 1409
 1281410                foreach (var tParam in info.GetSetMethod().GetParameters())
 1411                {
 341412                    tSetMethodBuilder.DefineParameter(tParam.Position + 1, AttributesForParam(tParam), tParam.Name);
 1413                }
 1414            }
 1415
 981416            EmitProperty(
 981417                typeBuilder,
 981418                tGetMethodBuilder,
 981419                tMp,
 981420                info,
 981421                tSetMethodBuilder,
 981422                emitInfo);
 981423        }
 1424        private abstract class EmitInfo
 1425        {
 1426            public string Name { get; set; }
 1427            public string Alias { get; set; }
 1428
 6901429            protected EmitInfo()
 1430            {
 6901431                _callSiteName =
 6901432                    new Lazy<string>(
 6901433                        () => $"Impromptu_Callsite_{Name}_{Guid.NewGuid():N}");
 6901434            }
 1435
 1436            private readonly Lazy<string> _callSiteName;
 1437            public string CallSiteName
 1438            {
 6901439                get { return _callSiteName.Value; }
 1440            }
 1441            public bool NonRecursive { get; set; }
 1442            public bool DefaultInterfaceImplementation { get; set; }
 1443            public IEnumerable<string> ArgNames { get; set; }
 1444            public Type[] ResolvedParamTypes { get; set; }
 1445            public Type ResolveReturnType { get; set; }
 1446            public Type CallSiteType { get; set; }
 1447            public Type ContextType { get; set; }
 1448
 1449        }
 1450
 1451        private class MethodEmitInfo : EmitInfo
 1452        {
 5871453            public MethodEmitInfo()
 1454            {
 5871455                CallSiteInvokeName = "Invoke_Method";
 5871456                CallSiteConvertName = "Convert_Method";
 5871457            }
 1458
 1459
 1460
 1461            public string CallSiteInvokeName { get; protected set; }
 1462            public string CallSiteConvertName { get; protected set; }
 1463
 1464            public Type CallSiteConvertFuncType { get; set; }
 1465            public Type CallSiteInvokeFuncType { get; set; }
 1466        }
 1467
 1468        public static CustomAttributeBuilder ToCustomAttributeBuilder(CustomAttributeData customAttributeData)
 1469        {
 81470            return new CustomAttributeBuilder(
 81471                customAttributeData.Constructor,
 81472                customAttributeData.ConstructorArguments
 81473                    .Select(
 81474                        arg =>
 81475                            arg.Value?.GetType()
 81476                            == typeof(ReadOnlyCollection<CustomAttributeTypedArgument>)
 81477                                ? ((ReadOnlyCollection<CustomAttributeTypedArgument>)arg.Value)
 81478                                .Select(arrayArg => arrayArg.Value)
 81479                                .ToArray()
 81480                                : arg.Value
 81481                    )
 81482                    .ToArray(),
 81483                customAttributeData.NamedArguments
 81484                    .Where(arg => arg.MemberInfo.MemberType == MemberTypes.Property)
 81485                    .Select(arg => arg.MemberInfo)
 81486                    .Cast<PropertyInfo>()
 81487                    .ToArray(),
 81488                customAttributeData.NamedArguments
 81489                    .Where(arg => arg.MemberInfo.MemberType == MemberTypes.Property)
 81490                    .Select(arg => arg.TypedValue.Value)
 81491                    .ToArray(),
 81492                customAttributeData.NamedArguments
 81493                    .Where(arg => arg.MemberInfo.MemberType == MemberTypes.Field)
 81494                    .Select(arg => arg.MemberInfo)
 81495                    .Cast<FieldInfo>()
 81496                    .ToArray(),
 81497                customAttributeData.NamedArguments
 81498                    .Where(arg => arg.MemberInfo.MemberType == MemberTypes.Field)
 81499                    .Select(arg => arg.TypedValue.Value)
 81500                    .ToArray()
 81501            );
 1502        }
 1503
 1504
 1505        private void EmitProperty(
 1506            TypeBuilder typeBuilder,
 1507            MethodBuilder getMethodBuilder,
 1508            PropertyBuilder tMp,
 1509            PropertyInfo info,
 1510            MethodBuilder setMethodBuilder,
 1511            PropertyEmitInfo emitInfo
 1512        )
 1513        {
 1514
 981515            if (emitInfo.ResolvedIndexParamTypes == null) throw new ArgumentNullException(nameof(emitInfo), "ResolvedInd
 1516
 981517            if (getMethodBuilder != null)
 1518            {
 921519                var tIlGen = getMethodBuilder.GetILGenerator();
 921520                var tConvertCallsiteField = emitInfo.CallSiteType.GetFieldEvenIfGeneric(emitInfo.CallSiteConvertName);
 1521
 1522                //If it's an interface and not nonrecursive this will be true
 921523                var tRecurse = emitInfo.ResolveReturnType.IsInterface && !emitInfo.NonRecursive;
 1524
 1525                //If we want to do recursive Interfaces we need to test the interface before we dynamically cast
 921526                var tReturnLocal = tIlGen.DeclareLocal(tRecurse ? typeof(object) : emitInfo.ResolveReturnType);
 1527
 1528
 921529                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tConvertCallsiteField)))
 1530                {
 921531                    tIlGen.EmitDynamicConvertBinder(CSharpBinderFlags.None, emitInfo.ResolveReturnType, emitInfo.Context
 921532                    tIlGen.EmitCallsiteCreate(emitInfo.CallSiteConvertFuncType);
 921533                    tIlGen.Emit(OpCodes.Stsfld, tConvertCallsiteField);
 921534                }
 1535
 921536                var tInvokeGetCallsiteField = emitInfo.CallSiteType.GetFieldEvenIfGeneric(emitInfo.CallSiteInvokeGetName
 1537
 921538                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tInvokeGetCallsiteField)))
 1539                {
 921540                    tIlGen.EmitDynamicGetBinder(CSharpBinderFlags.None, emitInfo.Alias ?? emitInfo.Name, emitInfo.Contex
 921541                    tIlGen.EmitCallsiteCreate(emitInfo.CallSiteInvokeGetFuncType);
 921542                    tIlGen.Emit(OpCodes.Stsfld, tInvokeGetCallsiteField);
 921543                }
 1544
 1545
 1546
 1547
 921548                if (!tRecurse)
 1549                {
 861550                    tIlGen.Emit(OpCodes.Ldsfld, tConvertCallsiteField);
 861551                    tIlGen.Emit(OpCodes.Ldfld, tConvertCallsiteField.FieldType.GetFieldEvenIfGeneric("Target"));
 861552                    tIlGen.Emit(OpCodes.Ldsfld, tConvertCallsiteField);
 1553                }
 921554                tIlGen.Emit(OpCodes.Ldsfld, tInvokeGetCallsiteField);
 921555                tIlGen.Emit(OpCodes.Ldfld, tInvokeGetCallsiteField.FieldType.GetFieldEvenIfGeneric("Target"));
 921556                tIlGen.Emit(OpCodes.Ldsfld, tInvokeGetCallsiteField);
 921557                tIlGen.Emit(OpCodes.Ldarg_0);
 921558                tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Original)).GetGetMe
 1921559                for (var i = 1; i <= emitInfo.ResolvedIndexParamTypes.Length; i++)
 1560                {
 41561                    tIlGen.EmitLoadArgument(i);
 1562                }
 921563                tIlGen.EmitCallInvokeFunc(emitInfo.CallSiteInvokeGetFuncType);
 1564
 1565                //If we are are recursing than do it later
 921566                if (!tRecurse)
 1567                {
 861568                    tIlGen.EmitCallInvokeFunc(emitInfo.CallSiteConvertFuncType);
 1569                }
 1570
 921571                tIlGen.EmitStoreLocation(tReturnLocal.LocalIndex);
 1572
 1573
 1574                //If return type is interface and instance is not interface, try actlike
 921575                if (tRecurse)
 1576                {
 61577                    using (tIlGen.EmitBranchFalse(gen => gen.EmitLoadLocation(tReturnLocal.LocalIndex)))
 1578                    {
 61579                        tIlGen.EmitLoadLocation(tReturnLocal.LocalIndex);
 61580                        using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Isinst, emitInfo.ResolveReturnType)))
 1581                        {
 61582                            tIlGen.Emit(OpCodes.Ldarg_0);
 61583                            tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Maker))
 61584                            tIlGen.EmitLoadLocation(tReturnLocal.LocalIndex);
 61585                            tIlGen.Emit(OpCodes.Call, ActLikeRec.MakeGenericMethod(emitInfo.ResolveReturnType));
 61586                            tIlGen.Emit(OpCodes.Ret);
 61587                        }
 1588                    }
 1589                }
 1590
 921591                var tReturnLabel = tIlGen.DefineLabel();
 921592                tIlGen.Emit(OpCodes.Br_S, tReturnLabel);
 921593                tIlGen.MarkLabel(tReturnLabel);
 921594                if (tRecurse)
 1595                {
 61596                    tIlGen.Emit(OpCodes.Ldsfld, tConvertCallsiteField);
 61597                    tIlGen.Emit(OpCodes.Ldfld, tConvertCallsiteField.FieldType.GetFieldEvenIfGeneric("Target"));
 61598                    tIlGen.Emit(OpCodes.Ldsfld, tConvertCallsiteField);
 1599                }
 921600                tIlGen.EmitLoadLocation(tReturnLocal.LocalIndex);
 921601                if (tRecurse)
 1602                {
 61603                    tIlGen.EmitCallInvokeFunc(emitInfo.CallSiteConvertFuncType);
 1604                }
 1605
 921606                tIlGen.Emit(OpCodes.Ret);
 921607                tMp.SetGetMethod(getMethodBuilder);
 1608            }
 1609
 981610            if (setMethodBuilder != null)
 1611            {
 301612                var tIlGen = setMethodBuilder.GetILGenerator();
 301613                var tSetCallsiteField = emitInfo.CallSiteType.GetFieldEvenIfGeneric(emitInfo.CallSiteInvokeSetName);
 1614
 301615                using (tIlGen.EmitBranchTrue(gen => gen.Emit(OpCodes.Ldsfld, tSetCallsiteField)))
 1616                {
 301617                    tIlGen.EmitDynamicSetBinder(CSharpBinderFlags.None, emitInfo.Alias ?? emitInfo.Name, emitInfo.Contex
 301618                    tIlGen.EmitCallsiteCreate(emitInfo.CallSiteInvokeSetFuncType);
 301619                    tIlGen.Emit(OpCodes.Stsfld, tSetCallsiteField);
 301620                }
 301621                tIlGen.Emit(OpCodes.Ldsfld, tSetCallsiteField);
 301622                tIlGen.Emit(OpCodes.Ldfld, tSetCallsiteField.FieldType.GetFieldEvenIfGeneric("Target"));
 301623                tIlGen.Emit(OpCodes.Ldsfld, tSetCallsiteField);
 301624                tIlGen.Emit(OpCodes.Ldarg_0);
 301625                tIlGen.Emit(OpCodes.Callvirt, typeof(IActLikeProxy).GetProperty(nameof(IActLikeProxy.Original)).GetGetMe
 1281626                for (var i = 1; i <= emitInfo.ResolvedParamTypes.Length; i++)
 1627                {
 341628                    tIlGen.EmitLoadArgument(i);
 1629                }
 301630                tIlGen.EmitCallInvokeFunc(emitInfo.CallSiteInvokeSetFuncType);
 301631                tIlGen.Emit(OpCodes.Pop);
 301632                tIlGen.Emit(OpCodes.Ret);
 301633                tMp.SetSetMethod(setMethodBuilder);
 1634            }
 1635
 981636            if (info != null)
 1637            {
 1638
 2081639                foreach (var attrData in info.GetCustomAttributesData())
 1640                {
 81641                    tMp.SetCustomAttribute(ToCustomAttributeBuilder(attrData));
 1642                }
 1643            }
 981644        }
 1645
 1646
 1647        private Type UpdateCallsiteFuncType(Type tFuncGeneric, Type returnType, params Type[] argTypes)
 1648        {
 3181649            var tList = new List<Type> { typeof(CallSite), typeof(object) };
 3181650            tList.AddRange(argTypes);
 3181651            if (returnType != typeof(void))
 3181652                tList.Add(returnType);
 1653
 3181654            IEnumerable<Type> tTypeArguments = tList;
 1655
 1656
 3181657            var tDef = tFuncGeneric.GetGenericTypeDefinition();
 1658
 3181659            if (tDef.GetGenericArguments().Count() != tTypeArguments.Count())
 1660            {
 11661                tTypeArguments = tTypeArguments.Where(it => it.IsGenericParameter);
 1662            }
 1663
 3181664            var tFuncType = tDef.MakeGenericType(tTypeArguments.ToArray());
 1665
 3181666            return tFuncType;
 1667        }
 1668
 1669        private Type ReduceToElementType(Type type)
 1670        {
 10101671            if (type.IsByRef || type.IsPointer || type.IsArray)
 81672                return type.GetElementType();
 10021673            return type;
 1674        }
 1675
 1676
 1677
 1678
 1679        /// <summary>
 1680        /// Emits new delegate type of the call site func.
 1681        /// </summary>
 1682        /// <param name="argTypes">The arg types.</param>
 1683        /// <param name="returnType">Type of the return.</param>
 1684        /// <returns></returns>
 1685        public Type EmitCallSiteFuncType(IEnumerable<Type> argTypes, Type returnType)
 1686        {
 01687            return GenerateCallSiteFuncType(argTypes, returnType);
 1688        }
 1689
 1690        /// <summary>
 1691        /// Generates the delegate type of the call site function.
 1692        /// </summary>
 1693        /// <param name="argTypes">The arg types.</param>
 1694        /// <param name="returnType">Type of the return.</param>
 1695        /// <param name="methodInfo">The method info. Required for reference types or delegates with more than 16 argume
 1696        /// <param name="builder">The Type Builder. Required for reference types or delegates with more than 16 argument
 1697        /// <returns></returns>
 1698        internal Type GenerateCallSiteFuncType(IEnumerable<Type> argTypes, Type returnType, MethodInfo methodInfo = null
 1699        {
 14111700            bool tIsFunc = returnType != typeof(void);
 1701
 1702
 14111703            var tList = new List<Type> { typeof(CallSite), typeof(object) };
 14111704            tList.AddRange(argTypes.Select(it => (it.IsNotPublic && !it.IsByRef) ? typeof(object) : it));
 1705
 1706
 1707
 14111708            lock (DelegateCacheLock)
 1709            {
 1710
 1711
 1712                TypeHash tHash;
 1713
 14111714                if ((tList.Any(it => it.IsByRef) || tList.Count > 16) && methodInfo != null)
 1715                {
 51716                    tHash = TypeHash.Create(strictOrder: true, moreTypes: methodInfo);
 1717                }
 1718                else
 1719                {
 14061720                    tHash = TypeHash.Create(strictOrder: true, moreTypes: tList.Concat(new[] { returnType }).ToArray());
 1721                }
 1722
 14111723                if (_delegateCache.TryGetValue(tHash, out var tType))
 1724                {
 9991725                    return tType;
 1726                }
 1727
 4121728                if (tList.Any(it => it.IsByRef)
 4121729                    || (tIsFunc && tList.Count >= 16)
 4121730                    || (!tIsFunc && tList.Count >= 16))
 1731                {
 41732                    tType = GenerateFullDelegate(builder, returnType, tList, methodInfo);
 1733
 1734
 41735                    _delegateCache[tHash] = tType;
 41736                    return tType;
 1737                }
 1738
 1739
 1740
 4081741                if (tIsFunc)
 4011742                    tList.Add(returnType);
 1743
 4081744                var tFuncGeneric = GenericDelegateType(tList.Count, !tIsFunc);
 1745
 1746
 4081747                var tFuncType = tFuncGeneric.MakeGenericType(tList.ToArray());
 1748
 4081749                _delegateCache[tHash] = tFuncType;
 1750
 4081751                return tFuncType;
 1752
 1753            }
 1754
 1755
 1756
 14111757        }
 1758
 1759        // ReSharper disable UnusedParameter.Local
 1760        // May switch to nested types if i figure out how to do it, thus would need the typebuilder
 1761        private Type GenerateFullDelegate(TypeBuilder builder, Type returnType, IEnumerable<Type> types, MethodInfo info
 1762            // ReSharper restore UnusedParameter.Local
 1763        {
 41764            var tBuilder = Builder.DefineType(
 41765                $"Impromptu_{"Delegate"}_{Guid.NewGuid():N}",
 41766                TypeAttributes.Class | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.Public,
 41767                typeof(MulticastDelegate));
 1768
 41769            var tReplacedTypes = GetParamTypes(tBuilder, info);
 1770
 41771            var tParamTypes = info == null
 41772                ? types.ToList()
 41773                : info.GetParameters().Select(it => it.ParameterType).ToList();
 1774
 41775            if (tReplacedTypes != null)
 1776            {
 11777                tParamTypes = tReplacedTypes.Item2.ToList();
 1778            }
 1779
 41780            if (info != null)
 1781            {
 41782                tParamTypes.Insert(0, typeof(object));
 41783                tParamTypes.Insert(0, typeof(CallSite));
 1784            }
 1785
 41786            var tCon = tBuilder.DefineConstructor(
 41787                MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig |
 41788                MethodAttributes.RTSpecialName, CallingConventions.Standard,
 41789                new[] { typeof(object), typeof(IntPtr) });
 1790
 41791            tCon.SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
 1792
 41793            var tMethod = tBuilder.DefineMethod("Invoke",
 41794                MethodAttributes.Public | MethodAttributes.HideBySig |
 41795                MethodAttributes.NewSlot |
 41796                MethodAttributes.Virtual);
 1797
 41798            tMethod.SetReturnType(returnType);
 41799            tMethod.SetParameters(tParamTypes.ToArray());
 1800
 41801            if (info != null)
 1802            {
 161803                foreach (var tParam in info.GetParameters())
 1804                {
 1805                    //+3 because of the callsite and target are added
 41806                    tMethod.DefineParameter(tParam.Position + 3, AttributesForParam(tParam), tParam.Name);
 1807                }
 1808            }
 1809
 41810            tMethod.SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
 1811
 1812
 1813
 41814            return tBuilder.CreateTypeInfo();
 1815
 1816        }
 1817
 1818        private ParameterAttributes AttributesForParam(ParameterInfo param)
 1819        {
 7391820            return param.Attributes;
 1821        }
 1822
 1823        public AssemblyBuilderAccess AssemblyAccess { get; private set; }
 1824
 1825
 1826
 1827
 1828        private static void GenerateAssembly(string name, AssemblyBuilderAccess access, ref AssemblyBuilder ab, ref Modu
 1829        {
 21830            var tName = new AssemblyName(name);
 1831
 21832            ab =
 21833                CompatHelper.DefineDynamicAssembly(
 21834                    tName,
 21835                    access);
 1836
 21837            mb =
 21838
 21839#if NETFRAMEWORK
 21840                access.HasFlag(AssemblyBuilderAccess.Save)
 21841                    ? ab.DefineDynamicModule("MainModule", $"{tName.Name}.dll") :
 21842#endif
 21843
 21844                    ab.DefineDynamicModule("MainModule");
 21845        }
 1846    }
 1847}

Methods/Properties

ActLike(System.Object,System.Type[])
Create()
Create(System.Object[])
AllActLike(System.Collections.Generic.IEnumerable`1<System.Object>,System.Type[])
InitializeProxy(System.Type,System.Object,System.Collections.Generic.IEnumerable`1<System.Type>,System.Collections.Generic.IDictionary`2<System.String,System.Type>,ImpromptuInterface.Build.ActLikeMaker)
ActLike(System.Object,System.Type[])
ActLikeProperties(System.Object,System.Collections.Generic.IDictionary`2<System.String,System.Type>)
DynamicActLike(System.Object,System.Type[])
.ctor()
RecursiveActLikeForProxy(ImpromptuInterface.Build.ActLikeMaker,System.Object)
.ctor(System.Reflection.Emit.AssemblyBuilderAccess,System.String)
get_Builder()
BuildType(System.Type,System.Type,System.Type[])
BuildType(System.Type,System.Collections.Generic.IDictionary`2<System.String,System.Type>)
PreLoadProxy(System.Type,ImpromptuInterface.Build.ActLikeProxyAttribute)
PreLoadProxiesFromAssembly(System.Reflection.Assembly)
BuildTypeHelper(System.Reflection.Emit.ModuleBuilder,System.Type,System.Collections.Generic.IDictionary`2<System.String,System.Type>)
MakePropertyDescribedProperty(System.Reflection.Emit.ModuleBuilder,System.Reflection.Emit.TypeBuilder,System.Type,System.String,System.Type)
DefineCallsiteFieldForMethod(System.Reflection.Emit.TypeBuilder,ImpromptuInterface.Build.ActLikeMaker,System.String,System.Type,System.Collections.Generic.IEnumerable`1<System.Type>,System.Reflection.MethodInfo)
DefineCallsiteField(System.Reflection.Emit.TypeBuilder,ImpromptuInterface.Build.ActLikeMaker,System.String,System.Type,System.Type[])
.ctor(System.Reflection.MethodInfo)
.ctor(System.String,System.Type[])
Equals(ImpromptuInterface.Build.ActLikeMaker/MethodSigHash)
Equals(System.Object)
GetHashCode()
BuildTypeHelper(System.Reflection.Emit.ModuleBuilder,System.Type,System.Type[])
FlattenGenericParameters(System.Type)
ReplaceTypeWithGenericBuilder(System.Type,System.Collections.Generic.IDictionary`2<System.Type,System.Reflection.Emit.GenericTypeParameterBuilder>)
CustomAttributeTypeArgument(System.Reflection.CustomAttributeTypedArgument)
.cctor()
GenericDelegateType(System.Int32,System.Boolean)
GetAttributeBuilder(System.Reflection.CustomAttributeData)
MakeMethod(System.Reflection.Emit.ModuleBuilder,System.Reflection.MethodInfo,System.Reflection.Emit.TypeBuilder,System.Type,System.Boolean,System.Boolean)
DefineBuilderForCallSite(System.Reflection.Emit.ModuleBuilder,System.String)
GetParamTypes(System.Object,System.Reflection.MethodInfo)
EmitMethodBody(System.Reflection.Emit.MethodBuilder,System.Reflection.ParameterInfo[],ImpromptuInterface.Build.ActLikeMaker/MethodEmitInfo)
MakeProperty(System.Reflection.Emit.ModuleBuilder,System.Reflection.PropertyInfo,System.Reflection.Emit.TypeBuilder,System.Type,System.Boolean,System.Boolean)
.ctor()
.ctor()
MakeEvent(System.Reflection.Emit.ModuleBuilder,System.Reflection.EventInfo,System.Reflection.Emit.TypeBuilder,System.Type,System.Boolean)
EmitRemoveEvent(System.Reflection.Emit.EventBuilder,System.Reflection.Emit.MethodBuilder,System.Reflection.EventInfo,System.Reflection.MethodInfo,System.Reflection.FieldInfo,System.Reflection.FieldInfo,System.Reflection.FieldInfo,ImpromptuInterface.Build.ActLikeMaker/EmitEventInfo)
EmitAddEvent(System.Reflection.Emit.EventBuilder,System.Reflection.Emit.MethodBuilder,System.Reflection.EventInfo,System.Reflection.MethodInfo,System.Reflection.FieldInfo,System.Reflection.FieldInfo,System.Reflection.FieldInfo,ImpromptuInterface.Build.ActLikeMaker/EmitEventInfo)
MakePropertyHelper(System.Reflection.Emit.ModuleBuilder,System.Reflection.Emit.TypeBuilder,ImpromptuInterface.Build.ActLikeMaker/PropertyEmitInfo,System.Reflection.PropertyInfo)
.ctor()
get_CallSiteName()
.ctor()
ToCustomAttributeBuilder(System.Reflection.CustomAttributeData)
EmitProperty(System.Reflection.Emit.TypeBuilder,System.Reflection.Emit.MethodBuilder,System.Reflection.Emit.PropertyBuilder,System.Reflection.PropertyInfo,System.Reflection.Emit.MethodBuilder,ImpromptuInterface.Build.ActLikeMaker/PropertyEmitInfo)
UpdateCallsiteFuncType(System.Type,System.Type,System.Type[])
ReduceToElementType(System.Type)
EmitCallSiteFuncType(System.Collections.Generic.IEnumerable`1<System.Type>,System.Type)
GenerateCallSiteFuncType(System.Collections.Generic.IEnumerable`1<System.Type>,System.Type,System.Reflection.MethodInfo,System.Reflection.Emit.TypeBuilder)
GenerateFullDelegate(System.Reflection.Emit.TypeBuilder,System.Type,System.Collections.Generic.IEnumerable`1<System.Type>,System.Reflection.MethodInfo)
AttributesForParam(System.Reflection.ParameterInfo)
GenerateAssembly(System.String,System.Reflection.Emit.AssemblyBuilderAccess,System.Reflection.Emit.AssemblyBuilder&,System.Reflection.Emit.ModuleBuilder&)