private object ImplementDelegate(Type delegateType, IRpcChannel channel, int remoteInstanceId, int localInstanceId) { RpcTypeDefinition type; lock (_proxyImplementations) { var hash = CreateTypesHash(delegateType); if (!_proxyImplementations.TryGetValue(hash, out type)) { var tb = _moduleBuilder.DefineType($"{delegateType.Name}Shadow{Guid.NewGuid():n}"); var invokerField = CreateConstructor(tb); var(localField, remoteField) = ImplementIRpcObjectProxy(tb); CreateDestructor(tb, invokerField, localField, remoteField); ImplementMethod(tb, delegateType.GetMethod("Invoke"), invokerField, remoteField, false); type = new RpcTypeDefinition { Type = tb.CreateTypeInfo().AsType() }; type.LocalIdField = type.Type.GetField(localField.Name, BindingFlags.NonPublic | BindingFlags.Instance); type.RemoteIdField = type.Type.GetField(remoteField.Name, BindingFlags.NonPublic | BindingFlags.Instance); _proxyImplementations.Add(hash, type); } } var delObj = Activator.CreateInstance(type.Type, channel); Debug.Assert(type.LocalIdField != null, "type.LocalIdField != null"); Debug.Assert(type.RemoteIdField != null, "type.RemoteIdField != null"); type.LocalIdField.SetValue(delObj, localInstanceId); type.RemoteIdField.SetValue(delObj, remoteInstanceId); return(Delegate.CreateDelegate(delegateType, delObj, "Invoke")); }
private object ImplementInterfaces(Type[] interfaceTypes, IRpcChannel channel, int remoteInstanceId, int localInstanceId) { if (!AllowNonPublicInterfaceAccess) { if (interfaceTypes.All(interfaceType => interfaceType.IsInterface && !interfaceType.IsPublic && !interfaceType.IsNestedPublic)) { throw new RpcFailedException("Cannot get non public interface."); } } RpcTypeDefinition type; lock (_proxyImplementations) { var hash = CreateTypesHash(interfaceTypes); if (!_proxyImplementations.TryGetValue(hash, out type)) { /* #if !NETSTANDARD && DEBUG * ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("RpcDynamicTypes"), * AssemblyBuilderAccess.RunAndSave); #endif*/ //add a destructor so we can inform other side about us not needing the object anymore var tb = _moduleBuilder.DefineType($"I{Guid.NewGuid():N}Shadow"); var invokerField = CreateConstructor(tb); var(localField, remoteField) = ImplementIRpcObjectProxy(tb); CreateDestructor(tb, invokerField, localField, remoteField); var allInterfaceTypes = AllowNonPublicInterfaceAccess ? interfaceTypes : interfaceTypes.Where(i => i.IsPublic || i.IsNestedPublic); foreach (var intf in allInterfaceTypes) { tb.AddInterfaceImplementation(intf); foreach (var method in intf.GetMethods().Where(m => !m.IsSpecialName)) { ImplementMethod(tb, method, invokerField, remoteField, true); } foreach (var property in intf.GetProperties()) { var prop = tb.DefineProperty(property.Name, property.Attributes, property.PropertyType, null); if (property.GetMethod != null) { prop.SetGetMethod(ImplementMethod(tb, property.GetMethod, invokerField, remoteField, true)); } if (property.SetMethod != null) { prop.SetSetMethod(ImplementMethod(tb, property.SetMethod, invokerField, remoteField, true)); } } foreach (var evnt in intf.GetEvents()) { if (evnt.AddMethod != null) { ImplementMethod(tb, evnt.AddMethod, invokerField, remoteField, true); } if (evnt.RemoveMethod != null) { ImplementMethod(tb, evnt.RemoveMethod, invokerField, remoteField, true, true); } } } type = new RpcTypeDefinition { Type = tb.CreateTypeInfo().AsType() }; type.LocalIdField = type.Type.GetField(localField.Name, BindingFlags.NonPublic | BindingFlags.Instance); type.RemoteIdField = type.Type.GetField(remoteField.Name, BindingFlags.NonPublic | BindingFlags.Instance); _proxyImplementations.Add(hash, type); } } /* #if !NETSTANDARD && DEBUG * ab.Save(@"RpcDynamicTypes.dll"); #endif*/ var result = Activator.CreateInstance(type.Type, channel); Debug.Assert(type.LocalIdField != null, "type.LocalIdField != null"); Debug.Assert(type.RemoteIdField != null, "type.RemoteIdField != null"); type.LocalIdField.SetValue(result, localInstanceId); type.RemoteIdField.SetValue(result, remoteInstanceId); return(result); }