From 991006d260bb8b3099968fb335712387ed5568c9 Mon Sep 17 00:00:00 2001 From: Adam Craven Date: Wed, 17 Jul 2019 02:59:56 +1000 Subject: [PATCH 1/5] Change the real proxies to support ref / out parameters --- .gitignore | 2 +- .../Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs | 2 +- .../Runtime/Remoting/Proxies/DisposableRealProxy.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index d75a0de..2624663 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,4 @@ /src/ChannelAdam.Core.BehaviourSpecs/obj/Debug /src/ChannelAdam.Core.BehaviourSpecs/ChannelAdam.Core.BehaviourSpecs.csproj.user /src/ChannelAdam.Core/TransientFaultHandling.csproj.user -/src/.vs/ChannelAdam.Core/v15/Server/sqlite3 +/src/.vs diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs index 018d5e9..6df371c 100644 --- a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs @@ -61,7 +61,7 @@ protected override object InvokeMethod(IMethodCallMessage methodCallMessage, obj try { - result = methodInfo.Invoke(onThis, methodCallMessage.InArgs); + result = methodInfo.Invoke(onThis, methodCallMessage.Args); } catch (TargetInvocationException targetEx) { diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs index 216a5f5..805ecc1 100644 --- a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs @@ -229,8 +229,8 @@ public override IMessage Invoke(IMessage msg) returnMessage = new ReturnMessage( result, // Operation result - null, // Out arguments - 0, // Out arguments count + methodCallMessage.Args, // Out arguments + methodCallMessage.ArgCount, // Out arguments count methodCallMessage.LogicalCallContext, // Call context methodCallMessage); // Original message } From 12f99659d8b88b10ce8ee19eb9207895a89b1b32 Mon Sep 17 00:00:00 2001 From: Adam Craven Date: Thu, 18 Jul 2019 03:49:21 +1000 Subject: [PATCH 2/5] Support out and ref parameters while maintaining backwards compatability --- .../ChannelAdam.Core.BehaviourSpecs.csproj | 13 ++ .../RealProxy.feature | 19 +++ .../RealProxy.feature.cs | 142 ++++++++++++++++++ .../RealProxyUnitTestSteps.cs | 122 +++++++++++++++ .../TestDoubles/ITestCalculatorToProxy.cs | 9 ++ .../TestDoubles/TestCalculatorToProxy.cs | 22 +++ .../TestDoubles/TestObjectRealProxy.cs | 34 +++++ src/ChannelAdam.Core/ChannelAdam.Core.csproj | 2 + .../Proxies/DisposableObjectRealProxy.cs | 18 ++- .../Remoting/Proxies/DisposableRealProxy.cs | 7 +- .../Remoting/Proxies/IHasMutableArgs.cs | 7 + .../MethodCallMessageWithMutableArgs.cs | 69 +++++++++ 12 files changed, 454 insertions(+), 10 deletions(-) create mode 100644 src/ChannelAdam.Core.BehaviourSpecs/RealProxy.feature create mode 100644 src/ChannelAdam.Core.BehaviourSpecs/RealProxy.feature.cs create mode 100644 src/ChannelAdam.Core.BehaviourSpecs/RealProxyUnitTestSteps.cs create mode 100644 src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/ITestCalculatorToProxy.cs create mode 100644 src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/TestCalculatorToProxy.cs create mode 100644 src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/TestObjectRealProxy.cs create mode 100644 src/ChannelAdam.Core/Runtime/Remoting/Proxies/IHasMutableArgs.cs create mode 100644 src/ChannelAdam.Core/Runtime/Remoting/Proxies/MethodCallMessageWithMutableArgs.cs diff --git a/src/ChannelAdam.Core.BehaviourSpecs/ChannelAdam.Core.BehaviourSpecs.csproj b/src/ChannelAdam.Core.BehaviourSpecs/ChannelAdam.Core.BehaviourSpecs.csproj index a857f8a..0438140 100644 --- a/src/ChannelAdam.Core.BehaviourSpecs/ChannelAdam.Core.BehaviourSpecs.csproj +++ b/src/ChannelAdam.Core.BehaviourSpecs/ChannelAdam.Core.BehaviourSpecs.csproj @@ -76,13 +76,22 @@ + + True + True + RealProxy.feature + + True True StringExtensions.feature + + + XmlSerialisation.feature True @@ -108,6 +117,10 @@ Commanding.feature.cs + + SpecFlowSingleFileGenerator + RealProxy.feature.cs + SpecFlowSingleFileGenerator StringExtensions.feature.cs diff --git a/src/ChannelAdam.Core.BehaviourSpecs/RealProxy.feature b/src/ChannelAdam.Core.BehaviourSpecs/RealProxy.feature new file mode 100644 index 0000000..a808df4 --- /dev/null +++ b/src/ChannelAdam.Core.BehaviourSpecs/RealProxy.feature @@ -0,0 +1,19 @@ +Feature: Real Proxy + +@UnitTest +Scenario: RealProxy - UT-01 - Should return a value when calling a function through the object real proxy + Given a proxied function with a return value + When the proxied function with a return value is called + Then the value returned from the proxied function with a return value has the correct return value + +@UnitTest +Scenario: RealProxy - UT-02 - Should allow usage of ref parameters when calling a method through the object real proxy + Given a proxied method with ref parameters + When the proxied method with ref parameters is called + Then the ref parameters from the proxied method have the correct values + +@UnitTest +Scenario: RealProxy - UT-03 - Should allow usage of in, out and ref parameters when calling a function through the object real proxy + Given a proxied function with in, out and ref parameters + When the proxied function with in, out and ref parameters is called + Then the return value, out and ref parameters from the proxied function have the correct values diff --git a/src/ChannelAdam.Core.BehaviourSpecs/RealProxy.feature.cs b/src/ChannelAdam.Core.BehaviourSpecs/RealProxy.feature.cs new file mode 100644 index 0000000..dc7a553 --- /dev/null +++ b/src/ChannelAdam.Core.BehaviourSpecs/RealProxy.feature.cs @@ -0,0 +1,142 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (http://www.specflow.org/). +// SpecFlow Version:1.9.0.77 +// SpecFlow Generator Version:1.9.0.0 +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +#pragma warning disable +namespace ChannelAdam.Core.BehaviourSpecs +{ + using TechTalk.SpecFlow; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.9.0.77")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute()] + public partial class RealProxyFeature + { + + private static TechTalk.SpecFlow.ITestRunner testRunner; + +#line 1 "RealProxy.feature" +#line hidden + + [Microsoft.VisualStudio.TestTools.UnitTesting.ClassInitializeAttribute()] + public static void FeatureSetup(Microsoft.VisualStudio.TestTools.UnitTesting.TestContext testContext) + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Real Proxy", "", ProgrammingLanguage.CSharp, ((string[])(null))); + testRunner.OnFeatureStart(featureInfo); + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.ClassCleanupAttribute()] + public static void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestInitializeAttribute()] + public virtual void TestInitialize() + { + if (((TechTalk.SpecFlow.FeatureContext.Current != null) + && (TechTalk.SpecFlow.FeatureContext.Current.FeatureInfo.Title != "Real Proxy"))) + { + ChannelAdam.Core.BehaviourSpecs.RealProxyFeature.FeatureSetup(null); + } + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestCleanupAttribute()] + public virtual void ScenarioTearDown() + { + testRunner.OnScenarioEnd(); + } + + public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioStart(scenarioInfo); + } + + public virtual void ScenarioCleanup() + { + testRunner.CollectScenarioErrors(); + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("RealProxy - UT-01 - Should return a value when calling a function through the obj" + + "ect real proxy")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "Real Proxy")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestCategoryAttribute("UnitTest")] + public virtual void RealProxy_UT_01_ShouldReturnAValueWhenCallingAFunctionThroughTheObjectRealProxy() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("RealProxy - UT-01 - Should return a value when calling a function through the obj" + + "ect real proxy", new string[] { + "UnitTest"}); +#line 4 +this.ScenarioSetup(scenarioInfo); +#line 5 + testRunner.Given("a proxied function with a return value", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 6 + testRunner.When("the proxied function with a return value is called", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 7 + testRunner.Then("the value returned from the proxied function with a return value has the correct " + + "return value", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + this.ScenarioCleanup(); + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("RealProxy - UT-02 - Should allow usage of ref parameters when calling a method th" + + "rough the object real proxy")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "Real Proxy")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestCategoryAttribute("UnitTest")] + public virtual void RealProxy_UT_02_ShouldAllowUsageOfRefParametersWhenCallingAMethodThroughTheObjectRealProxy() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("RealProxy - UT-02 - Should allow usage of ref parameters when calling a method th" + + "rough the object real proxy", new string[] { + "UnitTest"}); +#line 10 +this.ScenarioSetup(scenarioInfo); +#line 11 + testRunner.Given("a proxied method with ref parameters", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 12 + testRunner.When("the proxied method with ref parameters is called", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 13 + testRunner.Then("the ref parameters from the proxied method have the correct values", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + this.ScenarioCleanup(); + } + + [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute()] + [Microsoft.VisualStudio.TestTools.UnitTesting.DescriptionAttribute("RealProxy - UT-03 - Should allow usage of in, out and ref parameters when calling" + + " a function through the object real proxy")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestPropertyAttribute("FeatureTitle", "Real Proxy")] + [Microsoft.VisualStudio.TestTools.UnitTesting.TestCategoryAttribute("UnitTest")] + public virtual void RealProxy_UT_03_ShouldAllowUsageOfInOutAndRefParametersWhenCallingAFunctionThroughTheObjectRealProxy() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("RealProxy - UT-03 - Should allow usage of in, out and ref parameters when calling" + + " a function through the object real proxy", new string[] { + "UnitTest"}); +#line 16 +this.ScenarioSetup(scenarioInfo); +#line 17 + testRunner.Given("a proxied function with in, out and ref parameters", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given "); +#line 18 + testRunner.When("the proxied function with in, out and ref parameters is called", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When "); +#line 19 + testRunner.Then("the return value, out and ref parameters from the proxied function have the corre" + + "ct values", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then "); +#line hidden + this.ScenarioCleanup(); + } + } +} +#pragma warning restore +#endregion + diff --git a/src/ChannelAdam.Core.BehaviourSpecs/RealProxyUnitTestSteps.cs b/src/ChannelAdam.Core.BehaviourSpecs/RealProxyUnitTestSteps.cs new file mode 100644 index 0000000..a811139 --- /dev/null +++ b/src/ChannelAdam.Core.BehaviourSpecs/RealProxyUnitTestSteps.cs @@ -0,0 +1,122 @@ +using ChannelAdam.Core.BehaviourSpecs.TestDoubles; +using ChannelAdam.TestFramework.MSTest; +using TechTalk.SpecFlow; + +namespace ChannelAdam.Core.BehaviourSpecs +{ + [Binding] + [Scope(Feature = "Real Proxy")] + public class RealProxyUnitSteps : MoqTestFixture + { + #region Private Fields + + private int _actualOutValue; + private int _actualReturnedValue; + private int _actualZAndRefResult; + private TestObjectRealProxy _calculatorRealProxy; + private int? _expectedOutValue; + private int? _expectedReturnedValue; + private int? _expectedZAndRefResult; + private ITestCalculatorToProxy _transparentCalculatorProxy; + private int _x; + private int _y; + + #endregion Private Fields + + #region Public Methods + + [BeforeScenario] + public void BeforeScenario() + { + _calculatorRealProxy = new TestObjectRealProxy(new TestCalculatorToProxy()); + _transparentCalculatorProxy = (ITestCalculatorToProxy)_calculatorRealProxy.GetTransparentProxy(); + + _x = 1; + _y = 2; + _actualZAndRefResult = 5; + Logger.Log($"INPUTS: x={_x} y={_y} z={_actualZAndRefResult}"); + } + + #endregion Public Methods + + #region Given + + [Given(@"a proxied function with a return value")] + public void GivenAProxiedFunctionWithAReturnValue() + { + _expectedReturnedValue = _x + _y; + _expectedOutValue = null; + _expectedZAndRefResult = null; + Logger.Log($"EXPECTED: return value={_expectedReturnedValue}"); + } + + [Given(@"a proxied function with in, out and ref parameters")] + public void GivenAProxiedFunctionWithInOutAndRefParameters() + { + _expectedReturnedValue = _expectedOutValue = _x + _y; + _expectedZAndRefResult = _x + _y + _actualZAndRefResult; + Logger.Log($"EXPECTED: return value={_expectedReturnedValue}, out value={_expectedOutValue}, ref result={_expectedZAndRefResult}"); + } + + [Given(@"a proxied method with ref parameters")] + public void GivenAProxiedMethodWithRefParameters() + { + _expectedReturnedValue = null; + _expectedOutValue = null; + _expectedZAndRefResult = _x + _y + _actualZAndRefResult; + Logger.Log($"EXPECTED: ref result={_expectedZAndRefResult}"); + } + + #endregion Given + + #region When + + [When(@"the proxied function with a return value is called")] + public void WhenTheProxiedFunctionWithAReturnValueIsCalled() + { + _actualReturnedValue = _transparentCalculatorProxy.AddFunction(_x, _y); + Logger.Log($"ACTUAL: return value={_actualReturnedValue}"); + } + + [When(@"the proxied function with in, out and ref parameters is called")] + public void WhenTheProxiedFunctionWithInOutAndRefParametersIsCalled() + { + _actualReturnedValue = _transparentCalculatorProxy.AddFunctionWithAllParams(_x, _y, ref _actualZAndRefResult, out _actualOutValue); + Logger.Log($"ACTUAL: return value={_actualReturnedValue}, out value={_actualOutValue}, ref result={_actualZAndRefResult}"); + } + + [When(@"the proxied method with ref parameters is called")] + public void WhenTheProxiedMethodWithRefParametersIsCalled() + { + _transparentCalculatorProxy.AddMethodWithRefParams(_x, _y, ref _actualZAndRefResult); + Logger.Log($"ACTUAL: ref result={_actualZAndRefResult}"); + } + + #endregion When + + #region Then + + [Then(@"the value returned from the proxied function with a return value has the correct return value")] + [Then(@"the ref parameters from the proxied method have the correct values")] + [Then(@"the return value, out and ref parameters from the proxied function have the correct values")] + public void ThenAssertResultingValuesFromTheProxiedFunction() + { + if (_expectedReturnedValue.HasValue) + { + LogAssert.AreEqual("return value", _expectedReturnedValue, _actualReturnedValue); + } + + if (_expectedOutValue.HasValue) + { + LogAssert.AreEqual("out value", _expectedOutValue, _actualOutValue); + } + + if (_expectedZAndRefResult.HasValue) + { + LogAssert.AreEqual("ref result", _expectedZAndRefResult, _actualZAndRefResult); + } + } + + #endregion Then + } +} \ No newline at end of file diff --git a/src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/ITestCalculatorToProxy.cs b/src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/ITestCalculatorToProxy.cs new file mode 100644 index 0000000..18f4dc4 --- /dev/null +++ b/src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/ITestCalculatorToProxy.cs @@ -0,0 +1,9 @@ +namespace ChannelAdam.Core.BehaviourSpecs.TestDoubles +{ + public interface ITestCalculatorToProxy + { + int AddFunction(int x, int y); + int AddFunctionWithAllParams(int x, int y, ref int zAndRefResult, out int outResult); + void AddMethodWithRefParams(int x, int y, ref int refResult); + } +} \ No newline at end of file diff --git a/src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/TestCalculatorToProxy.cs b/src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/TestCalculatorToProxy.cs new file mode 100644 index 0000000..83e3651 --- /dev/null +++ b/src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/TestCalculatorToProxy.cs @@ -0,0 +1,22 @@ +namespace ChannelAdam.Core.BehaviourSpecs.TestDoubles +{ + public class TestCalculatorToProxy : ITestCalculatorToProxy + { + public int AddFunction(int x, int y) + { + return x + y; + } + + public void AddMethodWithRefParams(int x, int y, ref int zAndRefResult) + { + zAndRefResult = x + y + zAndRefResult; + } + + public int AddFunctionWithAllParams(int x, int y, ref int zAndRefResult, out int outResult) + { + outResult = x + y; + zAndRefResult = x + y + zAndRefResult; + return outResult; + } + } +} diff --git a/src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/TestObjectRealProxy.cs b/src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/TestObjectRealProxy.cs new file mode 100644 index 0000000..af11abd --- /dev/null +++ b/src/ChannelAdam.Core.BehaviourSpecs/TestDoubles/TestObjectRealProxy.cs @@ -0,0 +1,34 @@ +using ChannelAdam.Runtime.Remoting.Proxies; + +namespace ChannelAdam.Core.BehaviourSpecs.TestDoubles +{ + public class TestObjectRealProxy : DisposableObjectRealProxy + { + #region Public Fields + + public readonly TObjectToProxy obj; + + #endregion Public Fields + + #region Public Constructors + + public TestObjectRealProxy(TObjectToProxy objectToProxy) + { + this.obj = objectToProxy; + } + + #endregion Public Constructors + + #region Protected Properties + + protected override object ProxiedObject + { + get + { + return this.obj; + } + } + + #endregion Protected Properties + } +} \ No newline at end of file diff --git a/src/ChannelAdam.Core/ChannelAdam.Core.csproj b/src/ChannelAdam.Core/ChannelAdam.Core.csproj index 5178f41..13a66f6 100644 --- a/src/ChannelAdam.Core/ChannelAdam.Core.csproj +++ b/src/ChannelAdam.Core/ChannelAdam.Core.csproj @@ -96,6 +96,8 @@ + + diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs index 6df371c..c1579fc 100644 --- a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs @@ -50,18 +50,26 @@ protected DisposableObjectRealProxy(Type typeToProxy) /// The value of methodCallMessage.MethodBase cannot be cast to a MethodInfo. protected override object InvokeMethod(IMethodCallMessage methodCallMessage, object onThis) { - object result = null; - if (methodCallMessage == null) { throw new ArgumentNullException(nameof(methodCallMessage)); } + object result; var methodInfo = (MethodInfo)methodCallMessage.MethodBase; try { - result = methodInfo.Invoke(onThis, methodCallMessage.Args); + if (methodCallMessage is IHasMutableArgs hasMutableArgs) + { + // A little kludge to support ref and out parameters without having to change the signature of this InvokeMethod() to support passing the args in and out. + result = methodInfo.Invoke(onThis, hasMutableArgs.MutableArgs); + } + else + { + // Maintaining backwards compatability + result = methodInfo.Invoke(onThis, methodCallMessage.InArgs); + } } catch (TargetInvocationException targetEx) { @@ -73,10 +81,6 @@ protected override object InvokeMethod(IMethodCallMessage methodCallMessage, obj throw; } - ////catch (Exception) - ////{ - //// throw; - ////} return result; } diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs index 805ecc1..212fd42 100644 --- a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs @@ -217,19 +217,20 @@ public override IMessage Invoke(IMessage msg) } object result = null; + var methodCallMessageWrapper = new MethodCallMessageWithMutableArgs(methodCallMessage); if (methodCallMessage.MethodName == "Dispose") { - result = this.InvokeMethod(methodCallMessage, this); + result = this.InvokeMethod(methodCallMessageWrapper, this); } else { - result = this.InvokeMethod(methodCallMessage, this.ProxiedObject); + result = this.InvokeMethod(methodCallMessageWrapper, this.ProxiedObject); } returnMessage = new ReturnMessage( result, // Operation result - methodCallMessage.Args, // Out arguments + methodCallMessageWrapper.MutableArgs, // Out arguments methodCallMessage.ArgCount, // Out arguments count methodCallMessage.LogicalCallContext, // Call context methodCallMessage); // Original message diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/IHasMutableArgs.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/IHasMutableArgs.cs new file mode 100644 index 0000000..b2b75c3 --- /dev/null +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/IHasMutableArgs.cs @@ -0,0 +1,7 @@ +namespace ChannelAdam.Runtime.Remoting.Proxies +{ + public interface IHasMutableArgs + { + object[] MutableArgs { get; } + } +} \ No newline at end of file diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/MethodCallMessageWithMutableArgs.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/MethodCallMessageWithMutableArgs.cs new file mode 100644 index 0000000..3dee664 --- /dev/null +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/MethodCallMessageWithMutableArgs.cs @@ -0,0 +1,69 @@ +using System.Collections; +using System.Reflection; +using System.Runtime.Remoting.Messaging; + +namespace ChannelAdam.Runtime.Remoting.Proxies +{ + public class MethodCallMessageWithMutableArgs : IMethodCallMessage, IHasMutableArgs + { + #region Private Fields + + private readonly IMethodCallMessage _methodCallMessage; + + #endregion Private Fields + + #region Public Constructors + + public MethodCallMessageWithMutableArgs(IMethodCallMessage methodCallMessage) + { + _methodCallMessage = methodCallMessage; + MutableArgs = methodCallMessage.Args; + } + + #endregion Public Constructors + + #region Public Properties + + public int ArgCount => _methodCallMessage.ArgCount; + public object[] Args => _methodCallMessage.Args; + public bool HasVarArgs => _methodCallMessage.HasVarArgs; + public int InArgCount => _methodCallMessage.InArgCount; + + public object[] InArgs => _methodCallMessage.InArgs; + + public LogicalCallContext LogicalCallContext => _methodCallMessage.LogicalCallContext; + public MethodBase MethodBase => _methodCallMessage.MethodBase; + public string MethodName => _methodCallMessage.MethodName; + public object MethodSignature => _methodCallMessage.MethodSignature; + public object[] MutableArgs { get; } + public IDictionary Properties => _methodCallMessage.Properties; + public string TypeName => _methodCallMessage.TypeName; + public string Uri => _methodCallMessage.Uri; + + #endregion Public Properties + + #region Public Methods + + public object GetArg(int argNum) + { + return _methodCallMessage.GetArg(argNum); + } + + public string GetArgName(int index) + { + return _methodCallMessage.GetArgName(index); + } + + public object GetInArg(int argNum) + { + return _methodCallMessage.GetInArg(argNum); + } + + public string GetInArgName(int index) + { + return _methodCallMessage.GetInArgName(index); + } + + #endregion Public Methods + } +} \ No newline at end of file From e604b6a7f1e91b459c8e30e732035088133ae5a8 Mon Sep 17 00:00:00 2001 From: Adam Craven Date: Thu, 18 Jul 2019 03:51:35 +1000 Subject: [PATCH 3/5] Updated copyright --- .../Proxies/DisposableObjectRealProxy.cs | 2 +- .../Remoting/Proxies/DisposableRealProxy.cs | 8 +------- .../Remoting/Proxies/IHasMutableArgs.cs | 19 ++++++++++++++++++- .../MethodCallMessageWithMutableArgs.cs | 19 ++++++++++++++++++- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs index c1579fc..2c14044 100644 --- a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableObjectRealProxy.cs @@ -1,6 +1,6 @@ //----------------------------------------------------------------------- // -// Copyright (c) 2014 Adam Craven. All rights reserved. +// Copyright (c) 2014-2019 Adam Craven. All rights reserved. // // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs index 212fd42..068dad4 100644 --- a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs @@ -1,6 +1,6 @@ //----------------------------------------------------------------------- // -// Copyright (c) 2014 Adam Craven. All rights reserved. +// Copyright (c) 2014-2019 Adam Craven. All rights reserved. // // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,16 +18,10 @@ namespace ChannelAdam.Runtime.Remoting.Proxies { using System; - using System.Collections.Generic; - using System.Linq; - using System.Reflection; using System.Runtime.Remoting; using System.Runtime.Remoting.Messaging; using System.Runtime.Remoting.Proxies; using System.Security; - using System.Security.Permissions; - using System.Text; - using System.Threading.Tasks; /// /// Abstract class that implements the Dispose Pattern on top of a . diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/IHasMutableArgs.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/IHasMutableArgs.cs index b2b75c3..6ff6593 100644 --- a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/IHasMutableArgs.cs +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/IHasMutableArgs.cs @@ -1,4 +1,21 @@ -namespace ChannelAdam.Runtime.Remoting.Proxies +//----------------------------------------------------------------------- +// +// Copyright (c) 2019 Adam Craven. All rights reserved. +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//----------------------------------------------------------------------- + +namespace ChannelAdam.Runtime.Remoting.Proxies { public interface IHasMutableArgs { diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/MethodCallMessageWithMutableArgs.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/MethodCallMessageWithMutableArgs.cs index 3dee664..4ecb51d 100644 --- a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/MethodCallMessageWithMutableArgs.cs +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/MethodCallMessageWithMutableArgs.cs @@ -1,4 +1,21 @@ -using System.Collections; +//----------------------------------------------------------------------- +// +// Copyright (c) 2019 Adam Craven. All rights reserved. +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//----------------------------------------------------------------------- + +using System.Collections; using System.Reflection; using System.Runtime.Remoting.Messaging; From e1518336a5f84a9f87af8f068ca84ad648def5d1 Mon Sep 17 00:00:00 2001 From: Adam Craven Date: Thu, 18 Jul 2019 03:56:34 +1000 Subject: [PATCH 4/5] Updated variable name --- .../Remoting/Proxies/DisposableRealProxy.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs index 068dad4..84deeec 100644 --- a/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs +++ b/src/ChannelAdam.Core/Runtime/Remoting/Proxies/DisposableRealProxy.cs @@ -211,23 +211,23 @@ public override IMessage Invoke(IMessage msg) } object result = null; - var methodCallMessageWrapper = new MethodCallMessageWithMutableArgs(methodCallMessage); + var methodCallMessageWithMutableArgs = new MethodCallMessageWithMutableArgs(methodCallMessage); if (methodCallMessage.MethodName == "Dispose") { - result = this.InvokeMethod(methodCallMessageWrapper, this); + result = this.InvokeMethod(methodCallMessageWithMutableArgs, this); } else { - result = this.InvokeMethod(methodCallMessageWrapper, this.ProxiedObject); + result = this.InvokeMethod(methodCallMessageWithMutableArgs, this.ProxiedObject); } returnMessage = new ReturnMessage( - result, // Operation result - methodCallMessageWrapper.MutableArgs, // Out arguments - methodCallMessage.ArgCount, // Out arguments count - methodCallMessage.LogicalCallContext, // Call context - methodCallMessage); // Original message + result, // Operation result + methodCallMessageWithMutableArgs.MutableArgs, // Out arguments + methodCallMessage.ArgCount, // Out arguments count + methodCallMessage.LogicalCallContext, // Call context + methodCallMessage); // Original message } catch (Exception e) { From dc95f6e66fab946efbcae6331bfd71f55b91343e Mon Sep 17 00:00:00 2001 From: Adam Craven Date: Thu, 18 Jul 2019 23:29:26 +1000 Subject: [PATCH 5/5] Updated version in nuspec to 1.6.3 --- src/ChannelAdam.Core/ChannelAdam.Core.nuspec | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ChannelAdam.Core/ChannelAdam.Core.nuspec b/src/ChannelAdam.Core/ChannelAdam.Core.nuspec index 25a2492..e75d5af 100644 --- a/src/ChannelAdam.Core/ChannelAdam.Core.nuspec +++ b/src/ChannelAdam.Core/ChannelAdam.Core.nuspec @@ -2,7 +2,7 @@ ChannelAdam.Core - 1.6.2 + 1.6.3 ChannelAdam Core Library Adam Craven Adam Craven @@ -12,6 +12,8 @@ true DEPRECATED - see https://github.com/channeladam/ChannelAdam.Core/blob/master/README.md. A core library that provides helpful functionality including base classes for disposables and finalizers, weak events, proxies, support for retry policies, XML conversion/serialisation and embedded resources. +THIS LIBRARY IS NOW DEPRECATED. +1.6.3 - Enhanced ChannelAdam.Runtime.Remoting.Proxies to support out and ref method parameters. 1.6.1 - THIS LIBRARY IS NOW DEPRECATED. It has been replaced with the following .NET Standard libraries: - ChannelAdam.Commands