Add support for custom delegate-based events

This commit is contained in:
mclift 2017-03-11 18:02:01 +00:00
Родитель 9db4667a9c
Коммит 1e0e828a6a
4 изменённых файлов: 83 добавлений и 22 удалений

Просмотреть файл

@ -28,17 +28,31 @@ namespace Etg.SimpleStubs.CodeGen
classDclr = classDclr.AddMembers(eventDclr);
string eventName = eventSymbol.Name;
ParameterSyntax[] parameters = GetEventParameters(eventSymbol);
string onEventArgs = "sender";
string eventTriggerArgs = "sender";
if (parameters.Count() == 2)
bool isCustomDelegateEvent = IsCustomDelegateBasedEvent(eventSymbol, semanticModel);
ParameterSyntax[] parameters = GetEventParameters(eventSymbol, isCustomDelegateEvent);
string onEventArgs;
string eventTriggerArgs;
if (isCustomDelegateEvent)
{
onEventArgs += ", args";
eventTriggerArgs += ", args";
IMethodSymbol delegateInvokeMethodSymbol = ((INamedTypeSymbol)(eventSymbol.OriginalDefinition).Type).DelegateInvokeMethod;
onEventArgs = StubbingUtils.FormatParameters(delegateInvokeMethodSymbol);
eventTriggerArgs = onEventArgs;
}
else if (parameters.Count() == 1)
else
{
onEventArgs += ", null";
onEventArgs = "sender";
eventTriggerArgs = "sender";
if (parameters.Count() == 2)
{
onEventArgs += ", args";
eventTriggerArgs += ", args";
}
else if (parameters.Count() == 1)
{
onEventArgs += ", null";
}
}
string eventType = GetEventType(eventSymbol);
@ -69,17 +83,25 @@ namespace Etg.SimpleStubs.CodeGen
return classDclr;
}
private static ParameterSyntax[] GetEventParameters(IEventSymbol eventSymbol)
private static ParameterSyntax[] GetEventParameters(IEventSymbol eventSymbol, bool isCustomDelegateEvent)
{
List<ParameterSyntax> parameters = new List<ParameterSyntax>
{
SF.Parameter(SF.Identifier("sender")).WithType(SF.ParseTypeName("object"))
};
var parameters = new List<ParameterSyntax>();
INamedTypeSymbol type = (INamedTypeSymbol) (eventSymbol.Type);
if (type.TypeArguments.Any())
if (isCustomDelegateEvent)
{
parameters.Add(SF.Parameter(SF.Identifier("args"))
.WithType(SF.ParseTypeName(type.TypeArguments[0].Name)));
IMethodSymbol delegateInvokeMethodSymbol = ((INamedTypeSymbol)(eventSymbol.OriginalDefinition).Type).DelegateInvokeMethod;
parameters.AddRange(RoslynUtils.GetMethodParameterSyntaxList(delegateInvokeMethodSymbol).ToArray());
}
else
{
parameters.Add(SF.Parameter(SF.Identifier("sender")).WithType(SF.ParseTypeName("object")));
if (type.TypeArguments.Any())
{
parameters.Add(SF.Parameter(SF.Identifier("args"))
.WithType(SF.ParseTypeName(type.TypeArguments[0].Name)));
}
}
return parameters.ToArray();
@ -100,5 +122,18 @@ namespace Etg.SimpleStubs.CodeGen
{
return eventSymbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
}
private static bool IsCustomDelegateBasedEvent(IEventSymbol eventSymbol, SemanticModel semanticModel)
{
var genericEventType = semanticModel.Compilation.GetTypeByMetadataName("System.EventHandler`1");
var eventType = semanticModel.Compilation.GetTypeByMetadataName("System.EventHandler");
if (eventSymbol.Type.MetadataName.Equals(genericEventType.MetadataName) || eventSymbol.Type.MetadataName.Equals(eventType.MetadataName))
{
return false;
}
return true;
}
}
}

Просмотреть файл

@ -1,11 +1,8 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.MSBuild;
namespace Etg.SimpleStubs.CodeGen.Utils
{

Просмотреть файл

@ -113,4 +113,11 @@ namespace TestClassLibrary
void SetBoo<T, A>(T t, A a) where T : class, IDisposable, new() where A : new();
}
public delegate void CustomDelegateBasedHandler(int arg1, string arg2, object arg3);
public interface ICustomDelegateBasedEventExample
{
event CustomDelegateBasedHandler CustomDelegateEventOccurred;
}
}

Просмотреть файл

@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestClassLibrary;
namespace TestClassLibraryTest
@ -16,11 +17,32 @@ namespace TestClassLibraryTest
{
sender = s;
newNumber = num;
}
;
};
stub.PhoneNumberChanged_Raise(this, 55);
Assert.AreEqual(55, newNumber);
Assert.AreEqual(this, sender);
}
[TestMethod]
public void TestCustomDelegateBasedEventStub()
{
int arg1 = 0;
string arg2 = null;
object arg3 = null;
var stub = new StubICustomDelegateBasedEventExample();
stub.CustomDelegateEventOccurred += (i, s, o) =>
{
arg1 = i;
arg2 = s;
arg3 = o;
};
stub.CustomDelegateEventOccurred_Raise(55, "test", new Random(1));
Assert.AreEqual(55, arg1);
Assert.AreEqual("test", arg2);
Assert.AreEqual(typeof(Random), arg3.GetType());
}
}
}