public T CreateProxyWithFallback <T>(T subject, T fallback) { IFallbackProxyCreator creator; lock (_syncRoot) { var type = typeof(T); if (!_fallbackProxyCreators.TryGetValue(type, out creator)) { var description = _typeModel.Add(type, assumeByReference: true); creator = new FallbackProxyCreator <T>(_moduleBuilder, description); _fallbackProxyCreators.Add(typeof(T), creator); } } return((T)creator.Create(subject, fallback)); }
private static void ThrowIfIncompatible(Type expectedInterface, TypeModel actualTypeModel) { var expectedTypeModel = new TypeModel(); var expectedDescription = expectedTypeModel.Add(expectedInterface, assumeByReference: true); var actualDescription = actualTypeModel.Types.FirstOrDefault(x => x.AssemblyQualifiedName == expectedInterface.AssemblyQualifiedName); if (actualDescription == null) { throw new NotImplementedException($"The remote is missing interface: {expectedInterface.Name}"); } ThrowIfIncompatible(expectedDescription, actualDescription); }
public TypeModel GetTypeModel() { var typeModel = new TypeModel(); typeModel.Add <IInterfaces>(assumeByReference: true); typeModel.Add <IFiles>(assumeByReference: true); typeModel.Add <IShell>(assumeByReference: true); typeModel.Add <IServices>(assumeByReference: true); typeModel.Add <IProcesses>(assumeByReference: true); typeModel.Add <INetwork>(assumeByReference: true); typeModel.Add <IRegistry>(assumeByReference: true); return(typeModel); }
public T GetOrAdd(Type type) { lock (_syncRoot) { // Usually we already have generated the methods necessary to serialize / deserialize // and thus we can simply retrieve them from the dictionary T serializationMethods; if (!_serializationMethods.TryGetValue(type, out serializationMethods)) { var typeDescription = _typeModel.Add(type); // If that's not the case, then we'll have to generate them. // However we need to pay special attention to certain types, for example ByReference // types where the serialization method is IDENTICAL for each implementation. // // Usually we would call PatchType() everytime, however this method is very time-expensive // and therefore we will register both the type as well as the patched type, which // causes subsequent calls to RegisterType to no longer invoke PatchType. // // In essence PatchType is only ever invoked ONCE per type instead of for every call to RegisterType. var patchedType = PatchType(type); if (!_serializationMethods.TryGetValue(patchedType, out serializationMethods)) { var typeName = BuildTypeName(type); serializationMethods = _compiler.Prepare(typeName, typeDescription); try { _serializationMethods.Add(type, serializationMethods); _compiler.Compile(serializationMethods, this); } catch (Exception e) { Log.DebugFormat("Caught unexpected exception while trying to compile serialization methods for '{0}': {1}", typeDescription, e); _serializationMethods.Remove(type); throw; } if (type != patchedType) { _serializationMethods.Add(type, serializationMethods); } } } return(serializationMethods); } }