Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support of classes having methods with ref/out parameters and test #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions SexyProxy.Emit.Tests/RefParametersTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;

namespace SexyProxy.Emit.Tests
{
[TestFixture]
public class RefParametersTest
{
private string refParam;
private string outParam;
private string resultString;
private ITestClassWithRefParameters testClassWithRefParameters;
private ITestClassWithRefParameters proxy;
private MyTestRefClass myTestRefClass = new MyTestRefClass { Value = 10 };

[SetUp]
protected void SetUp()
{
refParam = "RefParam";
testClassWithRefParameters = new TestClassWithRefParameters();
proxy = Proxy.CreateProxy(testClassWithRefParameters, async invocation =>
{
var result = await invocation.Proceed();
return result;
});

}

[Test]
public void DoSomething()
{
proxy.DoSomething(1, ref refParam, out outParam);
ParametersAssert();
}

[Test]
public void GetSomeString()
{
resultString = proxy.GetSomeString(1, ref refParam, out outParam);
ParametersAssert();
ResultStringAssert();
}

[Test]
public void DoSomethingWithClassByRef()
{
proxy.DoSomethingWithClassByRef(ref myTestRefClass);
Assert.AreEqual(myTestRefClass.Value, 0);
}

[Test]
public void GetValueFromClassWithRef()
{
var result = proxy.GetValueFromClassWithRef(ref myTestRefClass);
Assert.AreEqual(myTestRefClass.Value, 0);
Assert.AreEqual(result, 0);
}

[Test]
public async void DoSomethingAsync()
{
resultString = await proxy.DoSomethingAsync();
ResultStringAssert();
}


private void ResultStringAssert()
{
Assert.AreEqual("ResultString", resultString);
}

private void ParametersAssert()
{
Assert.AreEqual("OutParam", outParam);
Assert.AreEqual("RefParamModified", refParam);
}

public interface ITestClassWithRefParameters
{
void DoSomething(int simpleParam, ref string refParam, out string outParam);

string GetSomeString(int simpleParam, ref string refParam, out string outParam);

void DoSomethingWithClassByRef(ref MyTestRefClass refClass);

int GetValueFromClassWithRef(ref MyTestRefClass refClass);

Task<string> DoSomethingAsync();
}

private class TestClassWithRefParameters : ITestClassWithRefParameters
{
public void DoSomething(int simpleParam, ref string refParam, out string outParam)
{
ModifyRefParameters(ref refParam, out outParam);
}

public string GetSomeString(int simpleParam, ref string refParam, out string outParam)
{
ModifyRefParameters(ref refParam, out outParam);
return "ResultString";
}

public void DoSomethingWithClassByRef(ref MyTestRefClass refClass)
{
refClass = new MyTestRefClass { Value = 0};
}

public int GetValueFromClassWithRef(ref MyTestRefClass refClass)
{
DoSomethingWithClassByRef(ref refClass);
return refClass.Value;
}

public async Task<string> DoSomethingAsync()
{
await GetValueAsync();
return "ResultString";
}

private Task GetValueAsync()
{
return Task.CompletedTask;
}

private void ModifyRefParameters(ref string refParam, out string outParam)
{
refParam+="Modified";
outParam = "OutParam";
}
}

public class MyTestRefClass
{
public int Value { get; set; }
}
}
}
3 changes: 2 additions & 1 deletion SexyProxy.Emit.Tests/SexyProxy.Emit.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SexyProxy.Emit.Tests</RootNamespace>
<AssemblyName>SexyProxy.Emit.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
Expand Down Expand Up @@ -58,6 +58,7 @@
<Compile Include="PredicatedProxyTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReadMeTests.cs" />
<Compile Include="RefParametersTest.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
Expand Down
14 changes: 12 additions & 2 deletions SexyProxy.Emit/EmitExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public static class EmitExtensions
new[] { typeof(string), typeof(BindingFlags), typeof(Binder), typeof(Type[]), typeof(ParameterModifier[]) });
private static readonly MethodInfo typeGetProperty = typeof(Type).GetMethod("GetProperty",
new[] { typeof(string), typeof(BindingFlags), typeof(Binder), typeof(Type), typeof(Type[]), typeof(ParameterModifier[]) });
private static readonly MethodInfo makeByRefTypeMethod = typeof(Type).GetMethod("MakeByRefType");

public static void EmitDefaultBaseConstructorCall(this ILGenerator il, Type baseType)
{
Expand All @@ -29,8 +30,17 @@ public static void EmitDefaultBaseConstructorCall(this ILGenerator il, Type base

public static void LoadType(this ILGenerator il, Type type)
{
il.Emit(OpCodes.Ldtoken, type);
il.Emit(OpCodes.Call, getTypeFromRuntimeHandleMethod);
if (type.IsByRef)
{
il.Emit(OpCodes.Ldtoken, type.GetElementType());
il.Emit(OpCodes.Call, getTypeFromRuntimeHandleMethod);
il.Emit(OpCodes.Callvirt, makeByRefTypeMethod);
}
else
{
il.Emit(OpCodes.Ldtoken, type);
il.Emit(OpCodes.Call, getTypeFromRuntimeHandleMethod);
}
}

public static void StoreMethodInfo(this ILGenerator il, FieldBuilder staticField, MethodInfo method)
Expand Down