Esempio n. 1
0
 public DuckTypeBuilder(MustImplementAttribute defaultAttribute, Type interfaceType, Type[] objectTypes)
 {
     _interfaceType    = interfaceType;
     _objectTypes      = objectTypes;
     _defaultAttribute = defaultAttribute;
 }
Esempio n. 2
0
        private bool BuildMembers(Type interfaceType)
        {
            FieldInfo    objectsField = typeof(DuckType).GetField("_objects", BindingFlags.NonPublic | BindingFlags.Instance);
            BindingFlags flags        = BindingFlags.Public | BindingFlags.Instance
                                        | (DuckTyping.AllowStaticMembers? BindingFlags.Static | BindingFlags.FlattenHierarchy: 0);

            foreach (MethodInfo interfaceMethod in interfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                MethodInfo targetMethod = null;
                int        typeIndex    = 0;

                for (; typeIndex < _objectTypes.Length; typeIndex++)
                {
                    if (_objectTypes[typeIndex] == null)
                    {
                        continue;
                    }

                    foreach (MethodInfo mi in _objectTypes[typeIndex].GetMethods(flags))
                    {
                        if (CompareMethodSignature(interfaceMethod, mi))
                        {
                            targetMethod = mi;
                            break;
                        }
                    }

                    if (targetMethod == null)
                    {
                        foreach (Type intf in _objectTypes[typeIndex].GetInterfaces())
                        {
                            if (intf.IsPublic || intf.IsNestedPublic)
                            {
                                foreach (MethodInfo mi in intf.GetMethods(flags))
                                {
                                    if (CompareMethodSignature(interfaceMethod, mi))
                                    {
                                        targetMethod = mi;
                                        break;
                                    }
                                }

                                if (targetMethod != null)
                                {
                                    break;
                                }
                            }
                        }
                    }

                    if (targetMethod != null)
                    {
                        break;
                    }
                }

                ParameterInfo[]     ips     = interfaceMethod.GetParameters();
                MethodBuilderHelper builder = _typeBuilder.DefineMethod(interfaceMethod);
                EmitHelper          emit    = builder.Emitter;

                if (targetMethod != null)
                {
                    Type targetType = targetMethod.DeclaringType;

                    if (!targetMethod.IsStatic)
                    {
                        emit
                        .ldarg_0
                        .ldfld(objectsField)
                        .ldc_i4(typeIndex)
                        .ldelem_ref
                        .end()
                        ;

                        if (targetType.IsValueType)
                        {
                            // For value types we have to use stack.
                            //
                            LocalBuilder obj = emit.DeclareLocal(targetType);

                            emit
                            .unbox_any(targetType)
                            .stloc(obj)
                            .ldloca(obj)
                            ;
                        }
                        else
                        {
                            emit
                            .castclass(targetType)
                            ;
                        }
                    }

                    foreach (ParameterInfo p in ips)
                    {
                        emit.ldarg(p);
                    }

                    if (targetMethod.IsStatic || targetMethod.IsFinal || targetMethod.DeclaringType.IsSealed)
                    {
                        emit
                        .call(targetMethod)
                        .ret();
                    }
                    else
                    {
                        emit
                        .callvirt(targetMethod)
                        .ret();
                    }
                }
                else
                {
                    // Method or property was not found.
                    // Insert an empty stub or stub that throws the NotImplementedException.
                    //
                    MustImplementAttribute attr = (MustImplementAttribute)
                                                  Attribute.GetCustomAttribute(interfaceMethod, typeof(MustImplementAttribute));

                    if (attr == null)
                    {
                        attr = (MustImplementAttribute)Attribute.GetCustomAttribute(
                            interfaceMethod.DeclaringType, typeof(MustImplementAttribute));
                        if (attr == null)
                        {
                            attr = _defaultAttribute;
                        }
                    }

                    // When the member is marked as 'Required' throw a build-time exception.
                    //
                    if (attr.Implement)
                    {
                        if (attr.ThrowException)
                        {
                            throw new TypeBuilderException(string.Format(
                                                               Resources.TypeBuilder_PublicMethodMustBeImplemented,
                                                               _objectTypes.Length > 0 && _objectTypes[0] != null ? _objectTypes[0].FullName : "???",
                                                               interfaceMethod));
                        }
                        else
                        {
                            // Implement == true, but ThrowException == false.
                            // In this case the null pointer will be returned.
                            // This mimics the 'as' operator behaviour.
                            //
                            return(false);
                        }
                    }

                    if (attr.ThrowException)
                    {
                        string message = attr.ExceptionMessage;

                        if (message == null)
                        {
                            message = string.Format(Resources.TypeBuilder_PublicMethodNotImplemented,
                                                    _objectTypes.Length > 0 && _objectTypes[0] != null ? _objectTypes[0].FullName : "???",
                                                    interfaceMethod);
                        }

                        emit
                        .ldstr(message)
                        .newobj(typeof(NotImplementedException), typeof(string))
                        .@throw
                        .end();
                    }
                    else
                    {
                        // Emit a 'do nothing' stub.
                        //
                        LocalBuilder returnValue = null;

                        if (interfaceMethod.ReturnType != typeof(void))
                        {
                            returnValue = emit.DeclareLocal(interfaceMethod.ReturnType);
                            emit.Init(returnValue);
                        }

                        // Initialize out parameters.
                        //
                        ParameterInfo[] parameters = ips;

                        if (parameters != null)
                        {
                            emit.InitOutParameters(parameters);
                        }

                        if (returnValue != null)
                        {
                            emit.ldloc(returnValue);
                        }

                        emit.ret();
                    }
                }
            }

            return(true);
        }
Esempio n. 3
0
        private bool BuildMembers(Type interfaceType)
        {
            FieldInfo    objectField = typeof(DuckType).GetField("_object", BindingFlags.NonPublic | BindingFlags.Instance);
            BindingFlags flags       = BindingFlags.Public | BindingFlags.Instance
                                       | (DuckTyping.AllowStaticMembers? BindingFlags.Static | BindingFlags.FlattenHierarchy: 0);

            foreach (MethodInfo interfaceMethod in interfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                ParameterInfo[] ips          = interfaceMethod.GetParameters();
                MethodInfo      targetMethod = null;

                foreach (MethodInfo mi in _objectType.GetMethods(flags))
                {
                    ParameterInfo[] ops = mi.GetParameters();

                    if (mi.Name == interfaceMethod.Name &&
                        mi.ReturnType == interfaceMethod.ReturnType &&
                        ops.Length == ips.Length)
                    {
                        targetMethod = mi;

                        for (int i = 0; i < ips.Length && targetMethod != null; i++)
                        {
                            ParameterInfo ip = ips[i];
                            ParameterInfo op = ops[i];

                            if (ip.ParameterType != op.ParameterType ||
                                ip.IsIn != op.IsIn ||
                                ip.IsOut != op.IsOut)
                            {
                                targetMethod = null;
                            }
                        }

                        if (targetMethod != null)
                        {
                            break;
                        }
                    }
                }

                MethodBuilderHelper builder = _typeBuilder.DefineMethod(interfaceMethod);
                EmitHelper          emit    = builder.Emitter;

                if (targetMethod != null)
                {
                    if (!targetMethod.IsStatic)
                    {
                        emit
                        .ldarg_0
                        .ldfld(objectField)
                        ;

                        if (_objectType.IsValueType)
                        {
                            // For value types we have to use stack.
                            //
                            LocalBuilder obj = emit.DeclareLocal(_objectType);

                            emit
                            .unbox_any(_objectType)
                            .stloc(obj)
                            .ldloca(obj)
                            ;
                        }
                        else
                        {
                            emit
                            .castclass(_objectType)
                            ;
                        }
                    }

                    foreach (ParameterInfo p in interfaceMethod.GetParameters())
                    {
                        emit.ldarg(p);
                    }

                    if (targetMethod.IsStatic)
                    {
                        emit
                        .call(targetMethod)
                        .ret();
                    }
                    else
                    {
                        emit
                        .callvirt(targetMethod)
                        .ret();
                    }
                }
                else
                {
                    // Method or property was not found.
                    // Insert an empty stub or stub that throws the NotImplementedException.
                    //
                    MustImplementAttribute attr = (MustImplementAttribute)
                                                  Attribute.GetCustomAttribute(interfaceMethod, typeof(MustImplementAttribute));

                    if (attr == null)
                    {
                        attr = (MustImplementAttribute)Attribute.GetCustomAttribute(
                            interfaceMethod.DeclaringType, typeof(MustImplementAttribute));
                        if (attr == null)
                        {
                            attr = MustImplementAttribute.Default;
                        }
                    }

                    // When the member is marked as 'Required' throw a build-time exception.
                    //
                    if (attr.Implement)
                    {
                        if (attr.ThrowException)
                        {
                            throw new TypeBuilderException(string.Format(
                                                               Resources.TypeBuilder_PublicMethodMustBeImplemented,
                                                               _objectType.FullName, interfaceMethod));
                        }
                        else
                        {
                            // Implement == true, but ThrowException == false.
                            // In this case the null pointer will be returned.
                            // This mimics the 'as' operator behaviour.
                            //
                            return(false);
                        }
                    }

                    if (attr.ThrowException)
                    {
                        string message = attr.ExceptionMessage;

                        if (message == null)
                        {
                            message = string.Format(Resources.TypeBuilder_PublicMethodNotImplemented,
                                                    _objectType.FullName, interfaceMethod);
                        }

                        emit
                        .ldstr(message)
                        .newobj(typeof(NotImplementedException), typeof(string))
                        .@throw
                        .end();
                    }
                    else
                    {
                        // Emit a 'do nothing' stub.
                        //
                        LocalBuilder returnValue = null;

                        if (interfaceMethod.ReturnType != typeof(void))
                        {
                            returnValue = emit.DeclareLocal(interfaceMethod.ReturnType);
                            emit.Init(returnValue);
                        }

                        // Initialize out parameters.
                        //
                        ParameterInfo[] parameters = interfaceMethod.GetParameters();

                        if (parameters != null)
                        {
                            emit.InitOutParameters(parameters);
                        }

                        if (returnValue != null)
                        {
                            emit.ldloc(returnValue);
                        }

                        emit.ret();
                    }
                }
            }

            return(true);
        }