Example #1
0
 private Function(Delegate @delegate, Type returnType, Type[] args, FunctionMValueParser[] parsers,
                  FunctionObjectParser[] objectParsers, FunctionStringParser[] stringParsers, FunctionTypeInfo[] typeInfos, CallArgsLengthCheck callArgsLengthCheck,
                  CallArgsLengthCheckPlayer callArgsLengthCheckPlayer, int requiredArgsCount)
 {
     this.@delegate                 = @delegate;
     this.returnType                = returnType;
     this.args                      = args;
     this.parsers                   = parsers;
     this.objectParsers             = objectParsers;
     this.stringParsers             = stringParsers;
     this.typeInfos                 = typeInfos;
     this.callArgsLengthCheck       = callArgsLengthCheck;
     this.callArgsLengthCheckPlayer = callArgsLengthCheckPlayer;
     this.requiredArgsCount         = requiredArgsCount;
 }
Example #2
0
        //TODO: for high optimization add ParseBoolUnsafe ect. that doesn't contains the mValue type check for scenarios where we already had to check the mValue type

        //TODO: add support for own function arguments parser for significant performance improvements with all benefits
        // Returns null when function signature isn't supported
        public static Function Create <T>(T func) where T : Delegate
        {
            var  type             = func.GetType();
            var  genericArguments = type.GetGenericArguments();
            Type returnType;

            if (type.Name.StartsWith("Func"))
            {
                // Return type is last generic argument
                // Function never has empty generic arguments, so no need for size check, but we do it anyway
                if (genericArguments.Length == 0)
                {
                    returnType = FunctionTypes.Void;
                }
                else
                {
                    returnType       = genericArguments[genericArguments.Length - 1];
                    genericArguments = genericArguments.SkipLast(1).ToArray();
                }
            }
            else
            {
                returnType = FunctionTypes.Void;
            }

            //TODO: check for unsupported types
            //TODO: check if last type is a object[] and add all to it that didnt fit with length, like (string bla, object[] args)
            //TODO: add parameter type attribute to annotate object[] with
            var parsers           = new FunctionMValueParser[genericArguments.Length];
            var objectParsers     = new FunctionObjectParser[genericArguments.Length];
            var stringParsers     = new FunctionStringParser[genericArguments.Length];
            var typeInfos         = new FunctionTypeInfo[genericArguments.Length];
            var requiredArgsCount = 0;

            for (int i = 0, length = genericArguments.Length; i < length; i++)
            {
                var arg      = genericArguments[i];
                var typeInfo = new FunctionTypeInfo(arg);
                typeInfos[i] = typeInfo;

                if (!typeInfo.IsNullable && !typeInfo.IsEventParams)
                {
                    requiredArgsCount++;
                }

                if (arg == FunctionTypes.Obj)
                {
                    //TODO: use MValue.ToObject here
                    parsers[i]       = FunctionMValueParsers.ParseObject;
                    objectParsers[i] = FunctionObjectParsers.ParseObject;
                    stringParsers[i] = FunctionStringParsers.ParseObject;
                }
                else if (arg == FunctionTypes.Bool)
                {
                    parsers[i]       = FunctionMValueParsers.ParseBool;
                    objectParsers[i] = FunctionObjectParsers.ParseBool;
                    stringParsers[i] = FunctionStringParsers.ParseBool;
                }
                else if (arg == FunctionTypes.Int)
                {
                    parsers[i]       = FunctionMValueParsers.ParseInt;
                    objectParsers[i] = FunctionObjectParsers.ParseInt;
                    stringParsers[i] = FunctionStringParsers.ParseInt;
                }
                else if (arg == FunctionTypes.Long)
                {
                    parsers[i]       = FunctionMValueParsers.ParseLong;
                    objectParsers[i] = FunctionObjectParsers.ParseLong;
                    stringParsers[i] = FunctionStringParsers.ParseLong;
                }
                else if (arg == FunctionTypes.UInt)
                {
                    parsers[i]       = FunctionMValueParsers.ParseUInt;
                    objectParsers[i] = FunctionObjectParsers.ParseUInt;
                    stringParsers[i] = FunctionStringParsers.ParseUInt;
                }
                else if (arg == FunctionTypes.ULong)
                {
                    parsers[i]       = FunctionMValueParsers.ParseULong;
                    objectParsers[i] = FunctionObjectParsers.ParseULong;
                    stringParsers[i] = FunctionStringParsers.ParseULong;
                }
                else if (arg == FunctionTypes.Float)
                {
                    parsers[i]       = FunctionMValueParsers.ParseFloat;
                    objectParsers[i] = FunctionObjectParsers.ParseFloat;
                    stringParsers[i] = FunctionStringParsers.ParseFloat;
                }
                else if (arg == FunctionTypes.Double)
                {
                    parsers[i]       = FunctionMValueParsers.ParseDouble;
                    objectParsers[i] = FunctionObjectParsers.ParseDouble;
                    stringParsers[i] = FunctionStringParsers.ParseDouble;
                }
                else if (arg == FunctionTypes.String)
                {
                    parsers[i]       = FunctionMValueParsers.ParseString;
                    objectParsers[i] = FunctionObjectParsers.ParseString;
                    stringParsers[i] = FunctionStringParsers.ParseString;
                }
                else if (arg.BaseType == FunctionTypes.Array)
                {
                    parsers[i]       = FunctionMValueParsers.ParseArray;
                    objectParsers[i] = FunctionObjectParsers.ParseArray;
                    stringParsers[i] = FunctionStringParsers.ParseArray;
                }
                else if (typeInfo.IsEntity)
                {
                    parsers[i]       = FunctionMValueParsers.ParseEntity;
                    objectParsers[i] = FunctionObjectParsers.ParseEntity;
                    stringParsers[i] = FunctionStringParsers.ParseEntity;
                }
                else if (typeInfo.IsDict)
                {
                    parsers[i]       = FunctionMValueParsers.ParseDictionary;
                    objectParsers[i] = FunctionObjectParsers.ParseDictionary;
                    stringParsers[i] = FunctionStringParsers.ParseDictionary;
                }
                else if (typeInfo.IsMValueConvertible)
                {
                    parsers[i]       = FunctionMValueParsers.ParseConvertible;
                    objectParsers[i] = FunctionObjectParsers.ParseConvertible;
                    stringParsers[i] = FunctionStringParsers.ParseConvertible;
                }
                else if (arg == FunctionTypes.FunctionType)
                {
                    parsers[i]       = FunctionMValueParsers.ParseFunction;
                    objectParsers[i] = FunctionObjectParsers.ParseFunction;
                    stringParsers[i] = FunctionStringParsers.ParseFunction;
                }
                else if (typeInfo.IsEnum)
                {
                    parsers[i]       = FunctionMValueParsers.ParseEnum;
                    objectParsers[i] = FunctionObjectParsers.ParseEnum;
                }
                else
                {
                    // Unsupported type
                    return(null);
                }
            }

            for (int i = 0, length = typeInfos.Length; i < length; i++)
            {
                if (!typeInfos[i].IsNullable || i - 1 >= length)
                {
                    continue;
                }
                if (!typeInfos[i + 1].IsNullable && !typeInfos[i + 1].IsEventParams)
                {
                    throw new ArgumentException(
                              "Method nullable needs to be at the end of the method. E.g. (int p1, int? p2, int p3?).");
                }
            }

            CallArgsLengthCheck       callArgsLengthCheck       = CheckArgsLength;
            CallArgsLengthCheckPlayer callArgsLengthCheckPlayer = CheckArgsLengthWithPlayer;

            if (typeInfos.Length > 0)
            {
                var lastTypeInfo = typeInfos[typeInfos.Length - 1];
                if (lastTypeInfo.IsEventParams)
                {
                    if (lastTypeInfo.IsList)
                    {
                        throw new ArgumentException("EventParams needs to be a array.");
                    }

                    callArgsLengthCheck       = CheckArgsLengthWithEventParams;
                    callArgsLengthCheckPlayer = CheckArgsLengthWithPlayerWithEventParams;
                }
            }

            return(new Function(func, returnType, genericArguments, parsers, objectParsers, stringParsers, typeInfos,
                                callArgsLengthCheck, callArgsLengthCheckPlayer, requiredArgsCount));
        }