private static AccessorMember MaybeSwapMetadataMember(ICustomAttributeProvider authority, AccessorMember member,
                                                              string profile)
        {
            foreach (var attribute in authority.GetAttributes <MetadataTypeAttribute>())
            {
                if (attribute.Profile != profile)
                {
                    continue;
                }

                var types = AccessorMemberTypes.None;
                types |= member.MemberType switch
                {
                    AccessorMemberType.Field => AccessorMemberTypes.Fields,
                    AccessorMemberType.Property => AccessorMemberTypes.Properties,
                    AccessorMemberType.Method => AccessorMemberTypes.Methods,
                    _ => throw new ArgumentOutOfRangeException()
                };

                var members = AccessorMembers.Create(attribute.MetadataType, types, member.Scope);
                foreach (var m in members)
                {
                    if (m.Name != member.Name)
                    {
                        continue;
                    }
                    member = m;
                    break;
                }
            }

            return(member);
        }
예제 #2
0
        private static ITypeCallAccessor CreateTypeCallAccessor(Type type,
                                                                AccessorMemberScope scope = AccessorMemberScope.All)
        {
            var members = AccessorMembers.Create(type, AccessorMemberTypes.Methods, scope);

            var name = type.CreateNameForCallAccessor();

            var tb = DynamicAssembly.Module.DefineType(
                name,
                TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit |
                TypeAttributes.AutoClass | TypeAttributes.AnsiClass);

            tb.AddInterfaceImplementation(typeof(ITypeCallAccessor));

            //
            // Type Type =>:
            //
            tb.MemberProperty(nameof(ITypeCallAccessor.Type), type,
                              typeof(ITypeCallAccessor).GetMethod($"get_{nameof(ITypeCallAccessor.Type)}"));

            //
            // object Call(object target, string name, params object[] args):
            //
            {
                var call = tb.DefineMethod(nameof(ITypeCallAccessor.Call),
                                           MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.HideBySig |
                                           MethodAttributes.Virtual | MethodAttributes.NewSlot,
                                           typeof(object), new[] { typeof(object), typeof(string), typeof(object[]) });

                var il = call.GetILGeneratorInternal();

                var branches = new Dictionary <AccessorMember, Label>();
                foreach (var member in members)
                {
                    if (!member.IsInstanceMethod)
                    {
                        continue;
                    }

                    branches.Add(member, il.DefineLabel());
                }

                il.DeclareLocal(typeof(string));
                il.DeclareLocal(typeof(object));
                il.Nop();
                il.Ldarg_2();
                il.Stloc_0();

                foreach (var member in members)
                {
                    if (!member.IsInstanceMethod)
                    {
                        continue;
                    }

                    il.Ldloc_0();
                    il.GotoIfStringEquals(member.Name, branches[member]);
                }

                foreach (var member in members)
                {
                    if (!member.IsInstanceMethod)
                    {
                        continue;
                    }

                    var method         = (MethodInfo)member.MemberInfo;
                    var parameters     = method.GetParameters();
                    var parameterTypes = parameters.Select(p => p.ParameterType).ToArray();

                    il.MarkLabel(branches[member]);
                    il.Ldarg_1();
                    il.CastOrUnbox(method.DeclaringType);

                    var returns = method.ReturnType != typeof(void);
                    if (returns)
                    {
                        continue;
                        throw new NotImplementedException();
                    }

                    if (parameters.Length > 0)
                    {
                        il.Ldarg_3();
                        il.Ldc_I4_S((byte)parameters.Length);
                        il.Ldelem_Ref();
                        il.Unbox_Any(parameterTypes[0]);
                    }

                    il.Callvirt(method);
                    il.Nop();

                    il.Ldtoken(typeof(void));
                    il.CallOrCallvirt(type, KnownMethods.GetTypeFromHandle);
                    il.Stloc_1();
                    il.Ldloc_1();
                    il.Ret();
                }

                il.Newobj(typeof(ArgumentNullException).GetConstructor(Type.EmptyTypes));
                il.Throw();

                tb.DefineMethodOverride(call, typeof(ITypeCallAccessor).GetMethod(nameof(ITypeCallAccessor.Call)));
            }

            var typeInfo = tb.CreateTypeInfo();

            return((ITypeCallAccessor)Activator.CreateInstance(typeInfo.AsType(), false));
        }
예제 #3
0
 private static AccessorMembers CreateReadAccessorMembers(Type type,
                                                          AccessorMemberTypes types = AccessorMemberTypes.Fields | AccessorMemberTypes.Properties,
                                                          AccessorMemberScope scope = AccessorMemberScope.All)
 {
     return(AccessorMembers.Create(type, types, scope));
 }
예제 #4
0
 private static AccessorMembers CreateAnonymousReadAccessorMembers(Type type)
 {
     return(AccessorMembers.Create(type, AccessorMemberTypes.Properties, AccessorMemberScope.Public));
 }
예제 #5
0
 private static AccessorMembers CreateWriteAccessorMembers(Type type, AccessorMemberTypes types,
                                                           AccessorMemberScope scope)
 {
     return(AccessorMembers.Create(type, types, scope));
 }