public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo)
 {
     if (typeInfo == null)
     {
         return(false);
     }
     return(IsAssignableFrom(typeInfo.AsType()));
 }
예제 #2
0
        internal static object Wrap(Type serviceInterfaceType, Func <string, System.Reflection.MethodInfo, object[], object> CallMethodAction, Func <string, System.Reflection.MethodInfo, object[], object> CallMethodAsyncAction)
        {
            //this method load GetCurrentMethod for xamarin linked assembly
            //System.Reflection.MethodBase fix = System.Reflection.MethodInfo.GetCurrentMethod();

            System.Reflection.AssemblyName assemblyName = new System.Reflection.AssemblyName(string.Format("tmp_{0}", serviceInterfaceType.FullName));
            string moduleName = string.Format("{0}.dll", assemblyName.Name);
            string ns         = serviceInterfaceType.Namespace;

            if (!string.IsNullOrEmpty(ns))
            {
                ns += ".";
            }
            ServiceContractAttribute attrib = serviceInterfaceType.GetCustomAttributes <ServiceContractAttribute>(true).Where(x => x.ServiceType == ServiceType.ServerService || x.ServiceType == ServiceType.ClientService || x.ServiceType == ServiceType.StreamService).FirstOrDefault();

#if (NET35)
            AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
                                                                                     AssemblyBuilderAccess.Run);
#elif (NET40)
            var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
                                                                         AssemblyBuilderAccess.RunAndCollect);
#else
            AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(assemblyName,
                                                                             AssemblyBuilderAccess.RunAndCollect);
#endif
#if (NETSTANDARD || NETCOREAPP || PORTABLE)
            ModuleBuilder module = assembly.DefineDynamicModule(moduleName);
#else
            ModuleBuilder module = assembly.DefineDynamicModule(moduleName, false);
#endif
            TypeBuilder type = module.DefineType(string.Format("{0}InterfaceWrapper_{1}", ns, serviceInterfaceType.Name),
                                                 System.Reflection.TypeAttributes.Class |
                                                 System.Reflection.TypeAttributes.AnsiClass |
                                                 System.Reflection.TypeAttributes.Sealed |
                                                 System.Reflection.TypeAttributes.NotPublic);
            type.AddInterfaceImplementation(serviceInterfaceType);

            // Define _Service0..N-1 private service fields
            FieldBuilder[] fields = new FieldBuilder[2];
#if (NETSTANDARD || NETCOREAPP)
            CustomAttributeBuilder cab = new CustomAttributeBuilder(
                System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(DebuggerBrowsableAttribute)).GetConstructor(new Type[] { typeof(DebuggerBrowsableState) }),
                new object[] { DebuggerBrowsableState.Never });
#else
            CustomAttributeBuilder cab = new CustomAttributeBuilder(
                typeof(DebuggerBrowsableAttribute).GetConstructor(new Type[] { typeof(DebuggerBrowsableState) }),
                new object[] { DebuggerBrowsableState.Never });
#endif

            fields[0] = type.DefineField(string.Format("_Service{0}", 0),
                                         serviceInterfaceType, System.Reflection.FieldAttributes.Public);

            fields[1] = type.DefineField(string.Format("_Service{0}", 1),
                                         serviceInterfaceType, System.Reflection.FieldAttributes.Public);

            // Ensure the field don't show up in the debugger tooltips
            fields[0].SetCustomAttribute(cab);
            fields[1].SetCustomAttribute(cab);

            // Define a simple constructor that takes all our services as arguments
            ConstructorBuilder ctor = type.DefineConstructor(System.Reflection.MethodAttributes.Public,
                                                             System.Reflection.CallingConventions.HasThis,
                                                             new Type[] { CallMethodAction.GetType(), CallMethodAsyncAction.GetType() });
            ILGenerator generator = ctor.GetILGenerator();

            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldarg_1);
            generator.Emit(OpCodes.Stfld, fields[0]);
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldarg_2);
            generator.Emit(OpCodes.Stfld, fields[1]);
            generator.Emit(OpCodes.Ret);
            foreach (Type serviceType in GetFullTypes(serviceInterfaceType))
            {
                // Implement all the methods of the interface
                foreach (System.Reflection.MethodInfo method in serviceType.GetListOfMethods())
                {
                    //generator.Emit(OpCodes.Pop);
                    System.Reflection.ParameterInfo[] args = method.GetParameters();
                    MethodBuilder methodImpl = type.DefineMethod(method.Name,
                                                                 System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Virtual,
                                                                 method.ReturnType, (from arg in args select arg.ParameterType).ToArray());
                    for (int i = 0; i < args.Length; i++)
                    {
                        ParameterBuilder parameterBuilder = methodImpl.DefineParameter(i + 1, System.Reflection.ParameterAttributes.None, args[i].Name);
                    }
                    // Generate code to simply call down into each service object
                    // Any return values are discarded, except the last one, which is returned
                    generator = methodImpl.GetILGenerator();

                    System.Reflection.MethodInfo invoke = null;
                    if (method.ReturnType.GetBaseType() == typeof(Task))
                    {
                        invoke = CallMethodAsyncAction.GetType().FindMethod("Invoke");
                        generator.Emit(OpCodes.Ldarg_0);          //stack [this]
                        generator.Emit(OpCodes.Ldfld, fields[1]); //stack
                    }
                    else
                    {
                        invoke = CallMethodAction.GetType().FindMethod("Invoke");
                        generator.Emit(OpCodes.Ldarg_0);          //stack [this]
                        generator.Emit(OpCodes.Ldfld, fields[0]); //stack
                    }


                    if (attrib == null)
                    {
                        throw new Exception("attrib not found");
                    }
                    string serviceName = attrib.Name;
                    if (attrib.ServiceType == ServiceType.ClientService)
                    {
                        serviceName = attrib.GetServiceName(false);
                    }
                    //add name of service
                    generator.Emit(OpCodes.Ldstr, serviceName);
                    System.Reflection.MethodInfo getCurgntMethod = typeof(System.Reflection.MethodBase).FindMethod("GetCurrentMethod");
                    if (getCurgntMethod == null)
                    {
                        throw new Exception("GetCurrentMethod not found");
                    }
                    //add current method info
                    generator.Emit(OpCodes.Call, getCurgntMethod);

                    //add obj[] argumants
                    if (args.Length > 0)
                    {
                        EmitInt32(generator, args.Length);
                        generator.Emit(OpCodes.Newarr, typeof(object));
                        for (int index = 0; index < args.Length; index++)
                        {
                            generator.Emit(OpCodes.Dup);
                            EmitInt32(generator, index);
                            switch (index)
                            {
                            case 0: generator.Emit(OpCodes.Ldarg_1); break;

                            case 1: generator.Emit(OpCodes.Ldarg_2); break;

                            case 2: generator.Emit(OpCodes.Ldarg_3); break;

                            default:
                                generator.Emit(index < 255 ? OpCodes.Ldarg_S
                                        : OpCodes.Ldarg, index + 1);
                                break;
                            }
                            //generator.Emit(OpCodes.Ldstr, args[index].Name);
                            generator.Emit(OpCodes.Box, args[index].ParameterType);
                            generator.Emit(OpCodes.Stelem_Ref);
                        }
                    }
                    else
                    {
                        EmitInt32(generator, 0);
                        generator.Emit(OpCodes.Newarr, typeof(object));
                    }
                    if (invoke == null)
                    {
                        throw new Exception("invoke not found");
                    }
                    generator.EmitCall(OpCodes.Call, invoke, null);

                    if (method.ReturnType == typeof(void))
                    {
                        generator.Emit(OpCodes.Pop);
                    }
                    else
                    {
                        generator.Emit(OpCodes.Castclass, method.ReturnType);
                        generator.Emit(OpCodes.Unbox_Any, method.ReturnType);
                    }
                    //generator.Emit(OpCodes.Castclass, method.ReturnType);
                    generator.Emit(OpCodes.Ret);
                }
            }
#if (NETSTANDARD || NETCOREAPP || PORTABLE)
            System.Reflection.TypeInfo newType = type.CreateTypeInfo();
            return(Activator.CreateInstance(newType.AsType(), CallMethodAction, CallMethodAsyncAction));
#else
            Type newType = type.CreateType();
            return(Activator.CreateInstance(newType, CallMethodAction, CallMethodAsyncAction));
#endif
        }