Exemple #1
0
        internal FnPointer(Delegate d, CallingConvention convention)
        {
            var def  = d.Method.GetBaseDefinition();
            var pars = def.GetParameters();

            if (Constants.X64)
            {
                var dt  = DelegateCreator.NewDelegateType(def.ReturnType, pars.Select(p => p.ParameterType).ToArray());
                var fd  = Delegate.CreateDelegate(dt, d.Target, d.Method);
                var ptr = Marshal.GetFunctionPointerForDelegate(fd);
                Int64 = ptr.ToInt64();
            }
            else
            {
//				var ptr = Marshal.GetFunctionPointerForDelegate(d);
//				convention = CallingConvention.X86CDecl;
//				Int64 = ptr.ToInt64();

                // TODO: Need fixing!!!
                throw new NotImplementedException("Managed method cannot be called from machine code in X86 mode by now.");
            }

            var args = pars.Select(p => p.ParameterType.GetVariableType()).ToArray();
            var ret  = def.ReturnType.GetVariableType();

            FunctionDeclaration = new FunctionDeclaration(convention, args, ret);
        }
        /// <SecurityNote>
        /// Critical: Calls critical method CreateDynamicMethod
        /// </SecurityNote>
        private DelegateCreator CreateDelegateCreator(Type targetType)
        {
            const BindingFlags helperFlags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly;

            // We are relying on WPF-generated delegate helper for now
            // Expected signature: internal Delegate _CreateDelegate(Type delegateType, string handler)
            // If it's not present, we just return a wrapper around Delegate.CreateDelegate, which
            // will fail if we the _localAssembly doesn't have RestrictedMemberAccess permission
            MethodInfo helper = targetType.GetMethod(KnownStrings.CreateDelegateHelper,
                                                     helperFlags, null, new Type[] { typeof(Type), typeof(string) }, null);

            if (helper == null)
            {
                if (_delegateCreatorWithoutHelper == null)
                {
                    _delegateCreatorWithoutHelper = CreateDelegateCreatorWithoutHelper();
                }
                return(_delegateCreatorWithoutHelper);
            }

            DynamicMethod dynamicMethod = CreateDynamicMethod(targetType.Name + "DelegateHelper",
                                                              typeof(Delegate), typeof(Type), typeof(object), typeof(string));
            ILGenerator ilGenerator = dynamicMethod.GetILGenerator();

            // We have to emit an indirect call through reflection to avoid the helper getting
            // inlined into the dynamic method, and potentially executing without access to private
            // members on the target type.
            Emit_LateBoundInvoke(ilGenerator, targetType, KnownStrings.CreateDelegateHelper,
                                 helperFlags | BindingFlags.InvokeMethod, 1, 0, 2);
            Emit_CastTo(ilGenerator, typeof(Delegate));
            ilGenerator.Emit(OpCodes.Ret);

            return((DelegateCreator)dynamicMethod.CreateDelegate(typeof(DelegateCreator)));
        }
        private bool Win32FuncWith <T, TDelegate>(IntPtr addressOrgFuncAddr, IntPtr orgFuncAddr, IntPtr proxyFuncAddr, Type returnType, out TDelegate saveOrgFunc) where T : Delegate
            where TDelegate : Delegate
        {
            saveOrgFunc = null;
            TDelegate orgFuncDelegate;

            Type genericType = typeof(T);

            if (genericType.IsGenericType == true)
            {
                Type   specificType = DelegateCreator.NewDelegateType(returnType, genericType.GetGenericArguments());
                object obj          = Marshal.GetDelegateForFunctionPointer(orgFuncAddr, specificType);
                orgFuncDelegate = obj as TDelegate;
            }
            else
            {
                orgFuncDelegate = Marshal.GetDelegateForFunctionPointer(orgFuncAddr, typeof(T)) as TDelegate;
            }

            if (WriteProtectedAddress(addressOrgFuncAddr, proxyFuncAddr) == false)
            {
                return(false);
            }

            _addressOrgFuncAddr = addressOrgFuncAddr;
            _orgFuncAddr        = orgFuncAddr;

            saveOrgFunc = orgFuncDelegate as TDelegate;
            return(true);
        }
Exemple #4
0
        public static CodeContext <T> CreateContext <T>()
        {
            var t = typeof(T);

            var  args = new Type[0];
            Type delType;

            if (t == typeof(Action))
            {
                delType = DelegateCreator.NewDelegateType(args);
            }
            else if (Utils.Actions.Contains(t.GetGenericTypeDefinition()))
            {
                var gargs = t.GetGenericArguments();
                args    = new Type[gargs.Length].InitializeWith(i => gargs[i]);
                delType = DelegateCreator.NewDelegateType(args);
            }
            else if (Utils.Funcs.Contains(t.GetGenericTypeDefinition()))
            {
                var gargs = t.GetGenericArguments();
                args = new Type[gargs.Length - 1].InitializeWith(i => gargs[i]);
                var ret = gargs.Last();
                delType = DelegateCreator.NewDelegateType(ret, args);
            }
            else
            {
                throw new ArgumentException();
            }
            var asm = new Assembler();
            var ctx = new CodeContext <T>(asm, delType);

            asm._codeContext = ctx;
            return(ctx);
        }
        private DelegateCreator CreateDelegateCreator(Type targetType)
        {
            if (targetType.GetMethod("_CreateDelegate", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, new Type[] { typeof(Type), typeof(string) }, null) == null)
            {
                if (this._delegateCreatorWithoutHelper == null)
                {
                    this._delegateCreatorWithoutHelper = this.CreateDelegateCreatorWithoutHelper();
                }
                return(this._delegateCreatorWithoutHelper);
            }
            DynamicMethod method      = this.CreateDynamicMethod(targetType.Name + "DelegateHelper", typeof(Delegate), new Type[] { typeof(Type), typeof(object), typeof(string) });
            ILGenerator   iLGenerator = method.GetILGenerator();

            short[] paramArgNums = new short[2];
            paramArgNums[1] = 2;
            this.Emit_LateBoundInvoke(iLGenerator, targetType, "_CreateDelegate", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, 1, paramArgNums);
            Emit_CastTo(iLGenerator, typeof(Delegate));
            iLGenerator.Emit(OpCodes.Ret);
            return((DelegateCreator)method.CreateDelegate(typeof(DelegateCreator)));
        }
Exemple #6
0
        public static CodeContext <T> CreateContext <T>(CallingConvention convention = CallingConvention.Default)
        {
            var t = typeof(T);

            var  args = new Type[0];
            Type ret  = null;
            Type delType;

            if (t == typeof(Action))
            {
                delType = DelegateCreator.NewDelegateType(args);
            }
            else if (Utils.Actions.Contains(t.GetGenericTypeDefinition()))
            {
                var gargs = t.GetGenericArguments();
                args    = new Type[gargs.Length].InitializeWith(i => gargs[i]);
                delType = DelegateCreator.NewDelegateType(args);
            }
            else if (Utils.Funcs.Contains(t.GetGenericTypeDefinition()))
            {
                var gargs = t.GetGenericArguments();
                args    = new Type[gargs.Length - 1].InitializeWith(i => gargs[i]);
                ret     = gargs.Last();
                delType = DelegateCreator.NewDelegateType(ret, args);
            }
            else
            {
                throw new ArgumentException();
            }

            var compiler = new Compiler();
            var ctx      = new CodeContext <T>(compiler, delType);

            compiler._codeContext   = ctx;
            compiler._codeProcessor = new CodeProcessor(compiler._assembler, compiler, compiler._codeContext);

            compiler.BeginFunction(args.Select(a => a.GetVariableType()).ToArray(), ret.GetVariableType(), convention);
            return(ctx);
        }
Exemple #7
0
        public static object InstantiatePatch(Type proxyType, List <object> baseCascade)
        {
            var(baseTypes, baseMethodSets) = BuildBaseCascadeInfo(baseCascade);

            var patchTargets = new Dictionary <MethodInfo, MethodInfo>();

            foreach (var method in proxyType.GetMethods(InstanceBinding))
            {
                var patchInfo = method.GetCustomAttribute <LogicProxyAttribute>();
                if (patchInfo == null)
                {
                    continue;
                }

                var patchTarget = GetPatchTarget();
                patchTargets.Add(patchTarget, method);

                MethodInfo GetPatchTarget()
                {
                    var t = method.FindMatchingMethod(baseMethodSets, true, (real, general) =>
                    {
                        if (real == general)
                        {
                            return(true);
                        }

                        if (real.IsClass && general == typeof(object))
                        {
                            return(true);
                        }

                        if (real.IsByRef && (general == typeof(IntPtr) || general == typeof(void *)))
                        {
                            return(true);
                        }

                        return(false);
                    });

                    //Patch real implementation, not V-table stub
                    return(t.GetDeclaredMember());
                }
            }

            var(fullInterface, proxyServiceBaseType) = GetProxyServiceInfo(proxyType);
            var proxyServiceInstanceProperty = proxyServiceBaseType.BaseType.GetProperty(nameof(ProxyService <object, object> .Instance));

            var redirectedMethods = new Dictionary <MethodInfo, MethodInfo>();

            foreach (var(target, redirectionTarget) in patchTargets)
            {
                var copy = CreateDuplicate(target);
                redirectedMethods.Add(target, copy);

                var args            = target.GetEffectiveParameterTypes();
                var redirectionStub = new DynamicMethod(target.Name + "_" + proxyType.Name + "_DetourStub", target.ReturnType, args);
                var IL = redirectionStub.GetILGenerator();

                if (redirectionTarget.IsStatic == false)
                {
                    IL.Emit(OpCodes.Call, proxyServiceInstanceProperty.GetMethod);
                }

                var offset = target.IsStatic ? 0 : 1;
                for (int i = 0; i < args.Length - offset; i++)
                {
                    IL.Emit(OpCodes.Ldarg, i + offset);
                }

                IL.Emit(OpCodes.Call, redirectionTarget);
                IL.Emit(OpCodes.Ret);

                RedirectMethod(target, redirectionStub);
            }

            object interfaceInstance;

            if (redirectedMethods.Count == 0 && baseTypes[0].Implements(fullInterface))
            {
                interfaceInstance = baseCascade[0];
            }
            else
            {
                var implementationTargets = new List <(MethodInfo Interface, int BaseIndex, MemberInfo ImplementationTarget)>();
                foreach (var method in fullInterface.GetAllInterfaceMethods())
                {
                    for (var i = 0; i < baseTypes.Length; i++)
                    {
                        var baseType       = baseTypes[i];
                        var implementation = baseType.TryFindImplementation(method, out var isInterfaceImplementation);

                        if (implementation != null)
                        {
                            if (redirectedMethods.TryGetValue(implementation, out var redirection))
                            {
                                //Direct call of duplicated method
                                implementation = redirection;
                            }
                            else if (implementation.IsAssemblyPublic())
                            {
                                //Direct call of implementing method is best choice, if accessible
                                //=> No op
                            }
                            else if (isInterfaceImplementation && method.IsAssemblyPublic())
                            {
                                //Direct interface call is second best choice
                                implementation = method;
                            }
                            else
                            {
                                //Fall-back to delegate proxy call to expose internal method
                                //=> No op
                            }

                            implementationTargets.Add((method, i, implementation));
                            goto matchFound;
                        }
                    }

                    if (method.IsProperty())
                    {
                        string dataTargetName = method.Name.Substring("get_".Length);
                        for (var i = 0; i < baseTypes.Length; i++)
                        {
                            var baseType   = baseTypes[i];
                            var dataTarget = TryFindDataTarget(baseType, method, dataTargetName);

                            if (dataTarget != null)
                            {
                                implementationTargets.Add((method, i, dataTarget));
                                goto matchFound;
                            }
                        }
                    }

                    throw new Exception("Could not find implementation or data target for " + method);
                    matchFound :;
                }

                var proxy = DynamicTypeBuilder.Create($"{fullInterface.Name}_" + proxyType.Name + proxyType.GetHashCode() + "_Proxy");
                proxy.Type.AddInterfaceImplementation(fullInterface);

                var baseIndexToField = new Dictionary <int, FieldBuilder>();
                foreach (var(_, baseIndex, _) in implementationTargets)
                {
                    if (baseIndexToField.ContainsKey(baseIndex))
                    {
                        continue;
                    }

                    var field = proxy.DeclareField(baseCascade[baseIndex].GetType());
                    baseIndexToField.Add(baseIndex, field);
                }

                var proxyDelegates = new List <(Delegate Instance, FieldBuilder Field)>();
                foreach (var(interfaceTarget, baseIndex, implementationTarget) in implementationTargets)
                {
                    var method = proxy.Type.DefineMethod(interfaceTarget.Name, MethodAttributes.Public | MethodAttributes.Virtual);
                    var IL     = method.GetILGenerator();

                    var argTypes = interfaceTarget.GetParameters().Select(x => x.ParameterType).ToArray();
                    method.SetParameters(argTypes);

                    var returnType = interfaceTarget.ReturnType;
                    method.SetReturnType(returnType);

                    proxy.Type.DefineMethodOverride(method, interfaceTarget);

                    if (implementationTarget is MethodInfo methodTarget)
                    {
                        EmitCallTarget(methodTarget);
                    }
                    else if (implementationTarget is FieldInfo fieldTarget)
                    {
                        var il = IL;
                        var isInstanceField = fieldTarget.IsStatic == false;

                        DynamicMethod proxyStub = null;
                        if (fieldTarget.IsAssemblyPublic())
                        {
                            if (isInstanceField)
                            {
                                LoadBaseInstance();
                            }
                        }
                        else
                        {
                            //Note: Nasty hack follows!
                            //Private field, dynamic type visibility rules, hacky solution, read below
                            var declaringType = fieldTarget.DeclaringType;
                            var args          = argTypes.Prepend(new[] { declaringType }).ToArray();
                            var stubName      = fieldTarget.Name + '_' + returnType.Name + "_ProxyAccessor";
                            proxyStub = new DynamicMethod(stubName, returnType, args, declaringType, true);
                            il        = proxyStub.GetILGenerator();

                            if (isInstanceField)
                            {
                                il.Emit(OpCodes.Ldarg_0);
                            }
                        }

                        if (returnType == typeof(void))
                        {
                            var op = isInstanceField ? OpCodes.Stfld : OpCodes.Stsfld;
                            il.Emit(OpCodes.Ldarg_1);
                            il.Emit(op, fieldTarget);
                        }
                        else
                        {
                            var op = isInstanceField ? OpCodes.Ldfld : OpCodes.Ldsfld;
                            il.Emit(op, fieldTarget);
                        }

                        if (proxyStub != null)
                        {
                            il.Emit(OpCodes.Ret);
                            EmitCallTarget(proxyStub);
                        }
                    }
                    else
                    {
                        throw new Exception("Unexpected implementation target " + implementationTarget.GetType());
                    }

                    IL.Emit(OpCodes.Ret);

                    void LoadBaseInstance()
                    {
                        IL.Emit(OpCodes.Ldarg_0);
                        IL.Emit(OpCodes.Ldfld, baseIndexToField[baseIndex]);
                    }

                    void PassArgs()
                    {
                        for (int i = 1; i <= argTypes.Length; i++)
                        {
                            IL.Emit(OpCodes.Ldarg, i);
                        }
                    }

                    void EmitCallTarget(MethodInfo callTarget)
                    {
                        //TODO: For some reason Mono is super unhappy when calling IL.Emit(Call, DynamicMethod)
                        //      => Proxy via delegate which is apparently fine
                        bool forceDelegateProxy = callTarget is DynamicMethod;

                        if (forceDelegateProxy || callTarget.IsAssemblyPublic() == false)
                        {
                            //Note: Nasty hack follows!
                            //Dynamic type has to follow all visibility rules normal assembly would have to so it can't call private methods directly
                            //Runtime delegates can reflect, call and expose private members, but can't instantiate interface
                            //=> Call proxy delegate inside proxy type to expose private method via public interface. We need to go deeper :)
                            var delegateType = DelegateCreator.NewDelegateType(callTarget, unboundInstanceCall: true);
                            //var proxyDelegate = Delegate.CreateDelegate(delegateType, callTarget);
                            var proxyDelegate = callTarget.CreateDelegate(delegateType);

                            var delegateField = proxy.DeclareField(delegateType);

                            IL.Emit(OpCodes.Ldarg_0);
                            IL.Emit(OpCodes.Ldfld, delegateField);

                            proxyDelegates.Add((proxyDelegate, delegateField));
                            callTarget = delegateType.GetMethod("Invoke");
                        }

                        LoadBaseInstance();
                        PassArgs();

                        var isInterfaceCall = callTarget.DeclaringType?.IsInterface ?? false;

                        IL.Emit(isInterfaceCall ? OpCodes.Callvirt : OpCodes.Call, callTarget);
                    }
                }

                proxy.DeclareCtorAndInitFields
                (
                    proxyDelegates.Select(x => x.Field).Concat(
                        baseIndexToField.Select(x => x.Value))
                );

                interfaceInstance = proxy.Instantiate
                                    (
                    proxyDelegates.Select(x => x.Instance).Concat(
                        baseIndexToField.Select(x => baseCascade[x.Key]))
                    .ToArray()
                                    );
            }

            var proxyInstance = Activator.CreateInstance(proxyType);

            proxyType.GetProperty(nameof(ProxyService <object, object> .Vanilla)).SetValue(proxyInstance, interfaceInstance);
            return(proxyInstance);
        }
Exemple #8
0
        public static void Install(Harmony harmony, object vanilla, Type vanillaInterfaceType)
        {
            Instance = Activator.CreateInstance <TInstance>();

            var vanillaImplType   = vanilla.GetType();
            var fullInterfaceType = typeof(TService);

            Log.Debug.PrintLine($"Installing {Instance.GetType()} -> {fullInterfaceType} -> {vanillaImplType} -> {vanillaInterfaceType}");

            var stubs   = new List <MethodBase>();
            var patches = new Dictionary <MethodBase, ServicePatch>();

            foreach (var method in typeof(TInstance).GetMethods(InstanceBinding))
            {
                var replace = method.GetCustomAttribute <HarmonyReplaceAttribute>();
                if (replace != null)
                {
                    var patch  = GetPatch();
                    int stubId = stubs.Count;

                    var interfaceMethod = patch.GetImplementedInterface(vanillaInterfaceType);
                    if (interfaceMethod != null)
                    {
                        stubs.Add(interfaceMethod);
                    }
                    else
                    {
                        //This is not method from vanilla interface
                        var extendedInterfaceMethod = patch.Target.FindMatchingMethod(fullInterfaceType.GetAllInterfaceMethods(), false);
                        if (extendedInterfaceMethod != null)
                        {
                            //We can proxy it via extended interface
                            stubs.Add(extendedInterfaceMethod);
                        }
                        else
                        {
                            //Or don't proxy it at all if there is no match in extended interface either
                            stubId = -1;
                        }
                    }

                    patch.VanillaReplace(method, stubId);
                    continue;
                }

                //TODO: Fix for `Vanilla` call
                var prefix = method.GetCustomAttribute <HarmonyPrefix>();
                if (prefix != null)
                {
                    GetPatch().Patch.AddPrefix(new HarmonyMethod(method));
                    continue;
                }

                var postfix = method.GetCustomAttribute <HarmonyPostfix>();
                if (postfix != null)
                {
                    GetPatch().Patch.AddPostfix(new HarmonyMethod(method));
                    continue;
                }

                var finalizer = method.GetCustomAttribute <HarmonyFinalizer>();
                if (finalizer != null)
                {
                    GetPatch().Patch.AddFinalizer(new HarmonyMethod(method));
                    continue;
                }

                ServicePatch GetPatch()
                {
                    var target = method.FindMatchingMethod(vanillaImplType.GetMethods(InstanceBinding), true, IsTypeMatching);

                    //Path real implementation, not V-table stub
                    target = target.GetDeclaredMember();

                    if (patches.TryGetValue(target, out var patch) == false)
                    {
                        patch = new ServicePatch(target, harmony.CreateProcessor(target));
                        patches.Add(target, patch);
                    }

                    return(patch);

                    bool IsTypeMatching(Type real, Type general)
                    {
                        if (real == general)
                        {
                            return(true);
                        }

                        if (real.IsClass && general == typeof(object))
                        {
                            return(true);
                        }

                        if (real.IsByRef && (general == typeof(IntPtr) || general == typeof(void *)))
                        {
                            return(true);
                        }

                        return(false);
                    }
                }
            }

            foreach (var(_, patch) in patches)
            {
                patch.Patch.Patch();
            }

            if (stubs.Count > 0 || vanillaInterfaceType != fullInterfaceType)
            {
                StubIndirections = new bool[stubs.Count];

                var proxy = PatchHelpers.CreateDynamicType($"{fullInterfaceType.Name}_Proxy");
                proxy.SetParent(typeof(object));
                proxy.AddInterfaceImplementation(fullInterfaceType);

                var stubsField      = AccessTools.Field(typeof(CreativeService <TInstance, TService>), "StubIndirections");
                var vanillaInstance = proxy.DefineField("__Vanilla", vanillaImplType, FieldAttributes.Public | FieldAttributes.InitOnly);

                var proxyDelegates         = new List <(Delegate Delegate, FieldInfo Field)>();
                var vanillaMethods         = vanillaInterfaceType.GetAllInterfaceMethods().ToHashSet();
                var declaredVanillaMethods = vanillaImplType.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

                foreach (var method in fullInterfaceType.GetAllInterfaceMethods())
                {
                    var args        = method.GetParameters();
                    var proxyMethod = proxy.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Virtual);
                    proxyMethod.SetReturnType(method.ReturnType);
                    proxyMethod.SetParameters(args.Select(x => x.ParameterType).ToArray());
                    proxy.DefineMethodOverride(proxyMethod, method);

                    var IL = proxyMethod.GetILGenerator();

                    var stubId = stubs.IndexOf(method);
                    if (stubId >= 0)
                    {
                        //Set stub mark
                        IL.Emit(OpCodes.Ldsfld, stubsField);
                        IL.Emit(OpCodes.Ldc_I4, stubId);
                        IL.Emit(OpCodes.Ldc_I4_1);
                        IL.Emit(OpCodes.Stelem_I1);
                    }

                    MethodInfo directCallTarget = null;
                    var        isInterfaceCall  = vanillaMethods.Contains(method);

                    if (isInterfaceCall == false)
                    {
                        directCallTarget = method.FindMatchingMethod(declaredVanillaMethods, true);

                        if (directCallTarget.IsAssemblyPublic() == false)
                        {
                            //Note: Nasty hack follows!
                            //Dynamic type has to follow all visibility rules normal assembly would so it can't call private methods directly
                            //Runtime delegates can reflect, call and expose private members, but can't instantiate interface
                            //=> Call proxy delegate inside proxy type to expose private method via public interface. We need to go deeper :)
                            var delegateType  = DelegateCreator.NewDelegateType(directCallTarget, unboundInstanceCall: true);
                            var proxyDelegate = Delegate.CreateDelegate(delegateType, directCallTarget);

                            var fieldName     = $"__ProxyDelegate_{directCallTarget.Name}_{proxyDelegates.Count}";
                            var delegateField = proxy.DefineField(fieldName, delegateType, FieldAttributes.Private | FieldAttributes.InitOnly);

                            IL.Emit(OpCodes.Ldarg_0); //This
                            IL.Emit(OpCodes.Ldfld, delegateField);

                            proxyDelegates.Add((proxyDelegate, delegateField));
                            directCallTarget = delegateType.GetMethod("Invoke");
                        }
                    }

                    if (directCallTarget == null || directCallTarget.IsStatic == false)
                    {
                        IL.Emit(OpCodes.Ldarg_0); //This
                        IL.Emit(OpCodes.Ldfld, vanillaInstance);
                    }

                    var argCount = args.Length;
                    for (int i = 1; i <= argCount; i++)
                    {
                        IL.Emit(OpCodes.Ldarg, i);
                    }

                    if (isInterfaceCall)
                    {
                        IL.Emit(OpCodes.Callvirt, method);
                    }
                    else
                    {
                        IL.Emit(OpCodes.Call, directCallTarget);
                    }

                    IL.Emit(OpCodes.Ret);
                }

                var ctorArgTypes = new[] { vanillaImplType }.Concat(proxyDelegates.Select(x => x.Field.FieldType));
                var ctor         = proxy.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, ctorArgTypes.ToArray());
                var cIL          = ctor.GetILGenerator();
                cIL.Emit(OpCodes.Ldarg_0);
                cIL.Emit(OpCodes.Call, proxy.BaseType.GetConstructor(Type.EmptyTypes));
                cIL.Emit(OpCodes.Ldarg_0);
                cIL.Emit(OpCodes.Ldarg_1);
                cIL.Emit(OpCodes.Stfld, vanillaInstance);

                for (int i = 0; i < proxyDelegates.Count; i++)
                {
                    cIL.Emit(OpCodes.Ldarg_0);
                    cIL.Emit(OpCodes.Ldarg, i + 2);
                    cIL.Emit(OpCodes.Stfld, proxyDelegates[i].Field);
                }

                cIL.Emit(OpCodes.Ret);

                var ctorArgs = new object[] { vanilla }.Concat(proxyDelegates.Select(x => x.Delegate));
                Instance.Vanilla = (TService)Activator.CreateInstance(proxy.CreateType(), ctorArgs.ToArray());
            }
            else
            {
                Instance.Vanilla = (TService)vanilla;
            }

            foreach (var property in typeof(TInstance).GetProperties(InstanceBinding | BindingFlags.Static))
            {
                if (property.HasAttribute <HarmonyPropertyAttribute>())
                {
                    property.InjectVanillaData(vanillaImplType, harmony);
                }
            }
        }
Exemple #9
0
 public TDelegate GetFunction <TDelegate>(string id) where TDelegate : Delegate
 {
     return(DelegateCreator.CreateDelegate <TDelegate>(GetAddress(id)));
 }
Exemple #10
0
 public TDelegate GetFunctionSafe <TDelegate>(string name) where TDelegate : Delegate
 {
     return(DelegateCreator.CreateDelegateSafe <TDelegate>(GetAddress(name)));
 }