diff --git a/MarshalByRefProxy/MarshalByRefProxy.csproj b/MarshalByRefProxy/MarshalByRefProxy.csproj index 085b134..19357d3 100644 --- a/MarshalByRefProxy/MarshalByRefProxy.csproj +++ b/MarshalByRefProxy/MarshalByRefProxy.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + netstandard2.0;net46 True sn.snk A library for marshalling any object by reference that do not require the object to inherit from MarshalByRefObject. @@ -24,7 +24,7 @@ - + diff --git a/MarshalByRefProxy/src/EmitProxy/BuildProxy.cs b/MarshalByRefProxy/src/EmitProxy/BuildProxy.cs index ca6db49..8c22792 100644 --- a/MarshalByRefProxy/src/EmitProxy/BuildProxy.cs +++ b/MarshalByRefProxy/src/EmitProxy/BuildProxy.cs @@ -30,7 +30,7 @@ namespace MarshalByRefProxy.Build -#if NET40 +#if NETFRAMEWORK internal static class CompatHelper { public static Type GetTypeInfo(this Type type) => type; @@ -78,7 +78,7 @@ public static TInterface RecursiveMarshalByRefAs(object target) wher } -#if NET40 +#if NETFRAMEWORK internal class TempBuilder : IDisposable { @@ -136,7 +136,12 @@ public static IDisposable WriteOutDll(string name) /// The main interface. /// The other interfaces. /// - 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) { @@ -145,7 +150,11 @@ 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; } @@ -153,8 +162,12 @@ public static Type BuildType(Type contextType, Type mainInterface, params Type[] } } - - public static Type BuildType(Type contextType) + + public static Type BuildType(Type contextType +#if NETFRAMEWORK + , System.Security.PermissionSet permissions=null +#endif + ) { lock (TypeCacheLock) { @@ -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; } @@ -178,7 +195,11 @@ public static Type BuildType(Type contextType) /// Type of the context. /// The informal interface. /// - public static Type BuildType(Type contextType, IDictionary informalInterface) + public static Type BuildType(Type contextType, IDictionary informalInterface +#if NETFRAMEWORK + , System.Security.PermissionSet permissions=null +#endif + ) { lock (TypeCacheLock) { @@ -186,7 +207,12 @@ public static Type BuildType(Type contextType, IDictionary informal 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; } @@ -262,15 +288,20 @@ from tType in assembly.GetTypes() return tSuccess; } - private static Type BuildTypeHelper(ModuleBuilder builder, Type contextType, IDictionary informalInterface) + private static Type BuildTypeHelper(ModuleBuilder builder, Type contextType, IDictionary 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) @@ -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)}), @@ -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; @@ -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 diff --git a/MarshalByRefProxy/src/EmitProxy/MarshalByRefAsProxySerializationHelper.cs b/MarshalByRefProxy/src/EmitProxy/MarshalByRefAsProxySerializationHelper.cs index de9f1e6..4db8dc1 100644 --- a/MarshalByRefProxy/src/EmitProxy/MarshalByRefAsProxySerializationHelper.cs +++ b/MarshalByRefProxy/src/EmitProxy/MarshalByRefAsProxySerializationHelper.cs @@ -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 } diff --git a/MarshalByRefProxy/src/MarshalByRefAsCaster.cs b/MarshalByRefProxy/src/MarshalByRefAsCaster.cs index 5a70f32..0a77e54 100644 --- a/MarshalByRefProxy/src/MarshalByRefAsCaster.cs +++ b/MarshalByRefProxy/src/MarshalByRefAsCaster.cs @@ -10,6 +10,9 @@ namespace MarshalByRefProxy public class MarshalByRefAsCaster : DynamicObject { public object Target { get; } +#if NETFRAMEWORK + private System.Security.PermissionSet _permissions; +#endif private List _interfaceTypes; public override bool TryConvert(System.Dynamic.ConvertBinder binder, out object result) @@ -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; } @@ -32,9 +39,17 @@ public override bool TryConvert(System.Dynamic.ConvertBinder binder, out object } - public MarshalByRefAsCaster(object target, IEnumerable types) + public MarshalByRefAsCaster(object target, + IEnumerable types +#if NETFRAMEWORK + , System.Security.PermissionSet permissions=null +#endif + ) { Target = target; +#if NETFRAMEWORK + _permissions = permissions; +#endif _interfaceTypes = types.ToList(); } diff --git a/MarshalByRefProxy/src/MarshalByRefProxy.cs b/MarshalByRefProxy/src/MarshalByRefProxy.cs index cb5209c..4588b74 100644 --- a/MarshalByRefProxy/src/MarshalByRefProxy.cs +++ b/MarshalByRefProxy/src/MarshalByRefProxy.cs @@ -69,15 +69,22 @@ public static IEnumerable AllMarshalByRef(this IEnumerable originalObje /// The original object can be annoymous type, System.DynamicObject as well as any others. /// Optional other interfaces. /// - public static TInterface MarshalByRefAs(this object originalDynamic, params Type[] otherInterfaces) where TInterface : class + public static TInterface MarshalByRefAs(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 @@ -109,9 +116,17 @@ public static dynamic UnmarshalByRef(this object proxiedObject) /// The original dynamic. /// The other interfaces. /// - 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 } @@ -132,16 +147,23 @@ public static TInterface Create(params object[] args) where /// The original dynamic. /// The property spec. /// - public static dynamic MarshalByRefAsProperties(this object originalDynamic, IDictionary propertySpec) + public static dynamic MarshalByRefAsProperties(this object originalDynamic, + IDictionary 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); @@ -170,9 +192,17 @@ internal static object InitializeProxy(Type proxytype, object original, IEnumera /// The original dynamic. /// The other interfaces. /// - public static IEnumerable AllMarshalByRefAs(this IEnumerable originalDynamic, params Type[] otherInterfaces) where TInterface : class + public static IEnumerable AllMarshalByRefAs(this IEnumerable originalDynamic, +#if NETFRAMEWORK + System.Security.PermissionSet permissions=null, +#endif + params Type[] otherInterfaces) where TInterface : class { +#if NETFRAMEWORK + return originalDynamic.Select(it => it.MarshalByRefAs(permissions, otherInterfaces)); +#else return originalDynamic.Select(it => it.MarshalByRefAs(otherInterfaces)); +#endif } /// @@ -181,14 +211,22 @@ public static IEnumerable AllMarshalByRefAs(this IEnumer /// The original dynamic. /// The other interfaces. /// - 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); diff --git a/README.md b/README.md index c990158..50cf4ef 100644 --- a/README.md +++ b/README.md @@ -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(new PermissionSet(PermissionState.Unrestricted)); +``` + ## Todos - [ ] `IAwaitable` - [ ] MarshalByRefWrapper Code Generators diff --git a/Tests/UnitTestImpromptuInterface/Basic.cs b/Tests/UnitTestImpromptuInterface/Basic.cs index 00f860c..8d7abe8 100644 --- a/Tests/UnitTestImpromptuInterface/Basic.cs +++ b/Tests/UnitTestImpromptuInterface/Basic.cs @@ -183,7 +183,7 @@ public void DoubleInterfacetest() tNew.Prop3 = Guid.NewGuid(); tNew.ReturnProp = new PropPoco(); - IInheritProp tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, typeof(ISimpeleClassProps)); + IInheritProp tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, null, typeof(ISimpeleClassProps)); @@ -277,7 +277,7 @@ public void DoublePropertyTest() tNew.Prop3 = Guid.NewGuid(); tNew.ReturnProp = new PropPoco(); - IInheritProp tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, typeof(IPropPocoProp)); + IInheritProp tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, null, typeof(IPropPocoProp)); @@ -295,20 +295,20 @@ public void EventPropertyCollisionTest() dynamic tNew = new ExpandoObject(); tNew.Event = 3; - IEventCollisions tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, typeof(IEvent)); + IEventCollisions tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, null, typeof(IEvent)); Assert.AreEqual(tNew.Event, tActsLike.Event); } - + [Test] public void InterfaceDirectDuplicateTest() { dynamic tNew = new ExpandoObject(); tNew.StartsWith = new Func(x => true); - - ISimpleStringMethod tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, typeof(ISimpleStringMethod)); + + ISimpleStringMethod tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, null, typeof(ISimpleStringMethod)); Assert.AreEqual(tNew.StartsWith("test"), tActsLike.StartsWith("test")); @@ -321,12 +321,12 @@ public void MethodCollisionTest() dynamic tNew = new ExpandoObject(); tNew.StartsWith = new Func(x => true); - ISimpleStringMethod tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, typeof(ISimpleStringMethodCollision)); + ISimpleStringMethod tActsLike = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew, null, typeof(ISimpleStringMethodCollision)); Assert.AreEqual(tNew.StartsWith("test"), tActsLike.StartsWith("test")); dynamic tNew2 = new ExpandoObject(); tNew2.StartsWith = new Func(x => 5); - ISimpleStringMethodCollision tActsLike2 = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew2, typeof(ISimpleStringMethodCollision)); + ISimpleStringMethodCollision tActsLike2 = MarshalByRefProxy.MarshalByRefProxy.MarshalByRefAs(tNew2, null, typeof(ISimpleStringMethodCollision)); Assert.AreEqual(tNew2.StartsWith("test"), tActsLike2.StartsWith("test")); } diff --git a/Tests/UnitTestImpromptuInterface/Support/Helper.cs b/Tests/UnitTestImpromptuInterface/Support/Helper.cs index cfe339e..b727e7e 100644 --- a/Tests/UnitTestImpromptuInterface/Support/Helper.cs +++ b/Tests/UnitTestImpromptuInterface/Support/Helper.cs @@ -17,7 +17,7 @@ public void WriteLine(string format, params object[] args) } } - public class Helper:AssertionHelper + public class Helper : AssertionHelper { public WriteLineContext TestContext { diff --git a/Version.props b/Version.props index 1a6fc17..019cbab 100644 --- a/Version.props +++ b/Version.props @@ -1,5 +1,5 @@ - 0.2.1 + 0.3.0 \ No newline at end of file