Skip to content

Commit

Permalink
Allow to assert permissions, support .NET Framework 4.6 and bump version
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaoses-Ib committed Jan 25, 2023
1 parent c12c829 commit 4e8b8cb
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 40 deletions.
4 changes: 2 additions & 2 deletions MarshalByRefProxy/MarshalByRefProxy.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>sn.snk</AssemblyOriginatorKeyFile>
<Description>A library for marshalling any object by reference that do not require the object to inherit from MarshalByRefObject.</Description>
Expand All @@ -24,7 +24,7 @@
<None Include="..\graphics\ImpromptuInterface-Icon.png" Pack="True" PackagePath="\" />
<PackageReference Include="Dynamitey" Version="2.0.*" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net40'">
<ItemGroup Condition="'$(TargetFramework)'=='net46'">
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
Expand Down
71 changes: 56 additions & 15 deletions MarshalByRefProxy/src/EmitProxy/BuildProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace MarshalByRefProxy.Build



#if NET40
#if NETFRAMEWORK
internal static class CompatHelper
{
public static Type GetTypeInfo(this Type type) => type;
Expand Down Expand Up @@ -78,7 +78,7 @@ public static TInterface RecursiveMarshalByRefAs<TInterface>(object target) wher
}


#if NET40
#if NETFRAMEWORK

internal class TempBuilder : IDisposable
{
Expand Down Expand Up @@ -136,7 +136,12 @@ public static IDisposable WriteOutDll(string name)
/// <param name="mainInterface">The main interface.</param>
/// <param name="otherInterfaces">The other interfaces.</param>
/// <returns></returns>
public static Type BuildType(Type contextType, Type mainInterface, params Type[] otherInterfaces)
public static Type BuildType(Type contextType,
Type mainInterface,
#if NETFRAMEWORK
System.Security.PermissionSet permissions=null,
#endif
params Type[] otherInterfaces)
{
lock (TypeCacheLock)
{
Expand All @@ -145,16 +150,24 @@ public static Type BuildType(Type contextType, Type mainInterface, params Type[]
Type tType;
if (!_typeHash.TryGetValue(tNewHash, out tType))
{
tType = BuildTypeHelper(Builder,contextType,new[]{mainInterface}.Concat(otherInterfaces).ToArray());
#if NETFRAMEWORK
tType = BuildTypeHelper(Builder, contextType, permissions, new[]{mainInterface}.Concat(otherInterfaces).ToArray());
#else
tType = BuildTypeHelper(Builder, contextType, new[]{mainInterface}.Concat(otherInterfaces).ToArray());
#endif
_typeHash[tNewHash] = tType;
}

return _typeHash[tNewHash];
}

}

public static Type BuildType(Type contextType)

public static Type BuildType(Type contextType
#if NETFRAMEWORK
, System.Security.PermissionSet permissions=null
#endif
)
{
lock (TypeCacheLock)
{
Expand All @@ -163,7 +176,11 @@ public static Type BuildType(Type contextType)
Type tType;
if (!_typeHash.TryGetValue(tNewHash, out tType))
{
#if NETFRAMEWORK
tType = BuildTypeHelper(Builder, contextType, permissions, new Type[] { });
#else
tType = BuildTypeHelper(Builder, contextType, new Type[] { });
#endif
_typeHash[tNewHash] = tType;
}

Expand All @@ -178,15 +195,24 @@ public static Type BuildType(Type contextType)
/// <param name="contextType">Type of the context.</param>
/// <param name="informalInterface">The informal interface.</param>
/// <returns></returns>
public static Type BuildType(Type contextType, IDictionary<string,Type> informalInterface)
public static Type BuildType(Type contextType, IDictionary<string,Type> informalInterface
#if NETFRAMEWORK
, System.Security.PermissionSet permissions=null
#endif
)
{
lock (TypeCacheLock)
{
var tNewHash = TypeHash.Create(contextType, informalInterface);
Type tType;
if (!_typeHash.TryGetValue(tNewHash, out tType))
{
#if NETFRAMEWORK
tType = BuildTypeHelper(Builder, contextType, informalInterface, permissions);
#else
tType = BuildTypeHelper(Builder, contextType, informalInterface);
#endif


_typeHash[tNewHash] = tType;
}
Expand Down Expand Up @@ -262,15 +288,20 @@ from tType in assembly.GetTypes()
return tSuccess;
}

private static Type BuildTypeHelper(ModuleBuilder builder, Type contextType, IDictionary<string,Type> informalInterface)
private static Type BuildTypeHelper(ModuleBuilder builder, Type contextType, IDictionary<string, Type> informalInterface
#if NETFRAMEWORK
, System.Security.PermissionSet permissions=null
#endif
)
{


var tB = builder.DefineType(
string.Format("MarshalByRefAs_{0}_{1}", "InformalInterface", Guid.NewGuid().ToString("N")), TypeAttributes.Public | TypeAttributes.Class,
typeof(MarshalByRefAsProxy));


#if NETFRAMEWORK
if (permissions != null)
tB.AddDeclarativeSecurity(System.Security.Permissions.SecurityAction.Assert, permissions);
#endif


foreach (var tInterface in informalInterface)
Expand Down Expand Up @@ -339,13 +370,23 @@ public override int GetHashCode()
}
}

private static Type BuildTypeHelper(ModuleBuilder builder,Type contextType,params Type[] interfaces)
private static Type BuildTypeHelper(ModuleBuilder builder, Type contextType,
#if NETFRAMEWORK
System.Security.PermissionSet permissions=null,
#endif
params Type[] interfaces
)
{

var tInterfacesMainList = interfaces.Distinct().ToArray();
var tB = builder.DefineType(
string.Format("AMarshalByRefAs_{0}_{1}", tInterfacesMainList.Count() > 0 ? tInterfacesMainList.First().Name : "", Guid.NewGuid().ToString("N")), TypeAttributes.Public | TypeAttributes.Class,
typeof(MarshalByRefAsProxy), tInterfacesMainList);

#if NETFRAMEWORK
if (permissions != null)
tB.AddDeclarativeSecurity(System.Security.Permissions.SecurityAction.Assert, permissions);
#endif

tB.SetCustomAttribute(
new CustomAttributeBuilder(typeof(MarshalByRefAsProxyAttribute).GetConstructor(new[]{typeof(Type).MakeArrayType(),typeof(Type)}),
Expand Down Expand Up @@ -541,7 +582,7 @@ private static CustomAttributeBuilder GetAttributeBuilder(CustomAttributeData da
private static void MakeMethod(ModuleBuilder builder,MethodInfo info, TypeBuilder typeBuilder, Type contextType, bool nonRecursive= false, bool defaultImp =true)
{


var tEmitInfo = new MethodEmitInfo {Name = info.Name, DefaultInterfaceImplementation = defaultImp, NonRecursive = nonRecursive};

var alias = info.GetCustomAttributes(typeof(AliasAttribute), false).FirstOrDefault() as AliasAttribute;
Expand Down Expand Up @@ -1754,7 +1795,7 @@ private static void GenerateAssembly(string name, AssemblyBuilderAccess access,
tName,
access);

#if NET40
#if NETFRAMEWORK
if (access== AssemblyBuilderAccess.RunAndSave || access == AssemblyBuilderAccess.Save)
mb = ab.DefineDynamicModule("MainModule", string.Format("{0}.dll", tName.Name));
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ public class MarshalByRefAsProxySerializationHelper : IObjectReference
public object GetRealObject(StreamingContext context)
{
var tInterfaces = Interfaces ?? MonoInterfaces.Select(it=>Type.GetType(it)).ToArray();
var tType =BuildProxy.BuildType(Context, tInterfaces.First(), tInterfaces.Skip(1).ToArray());
return MarshalByRefProxy.InitializeProxy(tType, Original, tInterfaces);
#if NETFRAMEWORK
var tType = BuildProxy.BuildType(Context, tInterfaces.First(), null, tInterfaces.Skip(1).ToArray());
#else
var tType = BuildProxy.BuildType(Context, tInterfaces.First(), tInterfaces.Skip(1).ToArray());
#endif
return MarshalByRefProxy.InitializeProxy(tType, Original, tInterfaces);
}

}
#endif
}
17 changes: 16 additions & 1 deletion MarshalByRefProxy/src/MarshalByRefAsCaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ namespace MarshalByRefProxy
public class MarshalByRefAsCaster : DynamicObject
{
public object Target { get; }
#if NETFRAMEWORK
private System.Security.PermissionSet _permissions;
#endif
private List<Type> _interfaceTypes;

public override bool TryConvert(System.Dynamic.ConvertBinder binder, out object result)
Expand All @@ -19,7 +22,11 @@ public override bool TryConvert(System.Dynamic.ConvertBinder binder, out object
if (binder.Type.IsInterface)
{
_interfaceTypes.Insert(0, binder.Type);
#if NETFRAMEWORK
result = MarshalByRefProxy.DynamicMarshalByRefAs(Target, _permissions, _interfaceTypes.ToArray());
#else
result = MarshalByRefProxy.DynamicMarshalByRefAs(Target, _interfaceTypes.ToArray());
#endif
return true;
}

Expand All @@ -32,9 +39,17 @@ public override bool TryConvert(System.Dynamic.ConvertBinder binder, out object
}


public MarshalByRefAsCaster(object target, IEnumerable<Type> types)
public MarshalByRefAsCaster(object target,
IEnumerable<Type> types
#if NETFRAMEWORK
, System.Security.PermissionSet permissions=null
#endif
)
{
Target = target;
#if NETFRAMEWORK
_permissions = permissions;
#endif
_interfaceTypes = types.ToList();
}

Expand Down
56 changes: 47 additions & 9 deletions MarshalByRefProxy/src/MarshalByRefProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,22 @@ public static IEnumerable<T> AllMarshalByRef<T>(this IEnumerable<T> originalObje
/// <param name="originalDynamic">The original object can be annoymous type, System.DynamicObject as well as any others.</param>
/// <param name="otherInterfaces">Optional other interfaces.</param>
/// <returns></returns>
public static TInterface MarshalByRefAs<TInterface>(this object originalDynamic, params Type[] otherInterfaces) where TInterface : class
public static TInterface MarshalByRefAs<TInterface>(this object originalDynamic,
#if NETFRAMEWORK
System.Security.PermissionSet permissions=null,
#endif
params Type[] otherInterfaces) where TInterface : class
{
Type tContext;
bool tDummy;
originalDynamic = originalDynamic.GetTargetContext(out tContext, out tDummy);
tContext = tContext.FixContext();

var tProxy = BuildProxy.BuildType(tContext, typeof(TInterface), otherInterfaces);

#if NETFRAMEWORK
var tProxy = BuildProxy.BuildType(tContext, typeof(TInterface), permissions, otherInterfaces);
#else
var tProxy = BuildProxy.BuildType(tContext, typeof(TInterface), otherInterfaces);
#endif


return
Expand Down Expand Up @@ -109,9 +116,17 @@ public static dynamic UnmarshalByRef(this object proxiedObject)
/// <param name="originalDynamic">The original dynamic.</param>
/// <param name="otherInterfaces">The other interfaces.</param>
/// <returns></returns>
public static dynamic MarshalByRefAs(this object originalDynamic, params Type[] otherInterfaces)
public static dynamic MarshalByRefAs(this object originalDynamic,
#if NETFRAMEWORK
System.Security.PermissionSet permissions=null,
#endif
params Type[] otherInterfaces)
{
#if NETFRAMEWORK
return new MarshalByRefAsCaster(originalDynamic, otherInterfaces, permissions);
#else
return new MarshalByRefAsCaster(originalDynamic, otherInterfaces);
#endif
}


Expand All @@ -132,16 +147,23 @@ public static TInterface Create<TTarget, TInterface>(params object[] args) where
/// <param name="originalDynamic">The original dynamic.</param>
/// <param name="propertySpec">The property spec.</param>
/// <returns></returns>
public static dynamic MarshalByRefAsProperties(this object originalDynamic, IDictionary<string, Type> propertySpec)
public static dynamic MarshalByRefAsProperties(this object originalDynamic,
IDictionary<string, Type> propertySpec
#if NETFRAMEWORK
, System.Security.PermissionSet permissions=null
#endif
)
{
Type tContext;
bool tDummy;
originalDynamic = originalDynamic.GetTargetContext(out tContext, out tDummy);
tContext = tContext.FixContext();

#if NETFRAMEWORK
var tProxy = BuildProxy.BuildType(tContext, propertySpec, permissions);
#else
var tProxy = BuildProxy.BuildType(tContext, propertySpec);


#endif

return
InitializeProxy(tProxy, originalDynamic, propertySpec: propertySpec);
Expand Down Expand Up @@ -170,9 +192,17 @@ internal static object InitializeProxy(Type proxytype, object original, IEnumera
/// <param name="originalDynamic">The original dynamic.</param>
/// <param name="otherInterfaces">The other interfaces.</param>
/// <returns></returns>
public static IEnumerable<TInterface> AllMarshalByRefAs<TInterface>(this IEnumerable<object> originalDynamic, params Type[] otherInterfaces) where TInterface : class
public static IEnumerable<TInterface> AllMarshalByRefAs<TInterface>(this IEnumerable<object> originalDynamic,
#if NETFRAMEWORK
System.Security.PermissionSet permissions=null,
#endif
params Type[] otherInterfaces) where TInterface : class
{
#if NETFRAMEWORK
return originalDynamic.Select(it => it.MarshalByRefAs<TInterface>(permissions, otherInterfaces));
#else
return originalDynamic.Select(it => it.MarshalByRefAs<TInterface>(otherInterfaces));
#endif
}

/// <summary>
Expand All @@ -181,14 +211,22 @@ public static IEnumerable<TInterface> AllMarshalByRefAs<TInterface>(this IEnumer
/// <param name="originalDynamic">The original dynamic.</param>
/// <param name="otherInterfaces">The other interfaces.</param>
/// <returns></returns>
public static dynamic DynamicMarshalByRefAs(object originalDynamic, params Type[] otherInterfaces)
public static dynamic DynamicMarshalByRefAs(object originalDynamic,
#if NETFRAMEWORK
System.Security.PermissionSet permissions=null,
#endif
params Type[] otherInterfaces)
{
Type tContext;
bool tDummy;
originalDynamic = originalDynamic.GetTargetContext(out tContext, out tDummy);
tContext = tContext.FixContext();

#if NETFRAMEWORK
var tProxy = BuildProxy.BuildType(tContext, otherInterfaces.First(), permissions, otherInterfaces.Skip(1).ToArray());
#else
var tProxy = BuildProxy.BuildType(tContext, otherInterfaces.First(), otherInterfaces.Skip(1).ToArray());
#endif

return InitializeProxy(tProxy, originalDynamic, otherInterfaces);

Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ public async Task TestTask()
```
Why can we await `IAwaitable`? Because C# can await any [awaitable expressions](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#11882-awaitable-expressions), which is exactly what `IAwaitable` stands for.

## Permissions (.NET Framework only)
Assert unrestricted permissions:
```csharp
using System.Security;
using System.Security.Permissions;

new UnmarshallableClass().MarshalByRefAs<IProxyInterface>(new PermissionSet(PermissionState.Unrestricted));
```

## Todos
- [ ] `IAwaitable<T>`
- [ ] MarshalByRefWrapper Code Generators
Expand Down
Loading

0 comments on commit 4e8b8cb

Please sign in to comment.