Skip to content

Commit 4bd429e

Browse files
author
Mihnea Rădulescu
committed
Updated event raising logic to only allow internal default constructors
1 parent ee276f3 commit 4bd429e

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

src/NSubstitute/Core/Events/RaiseEventWrapper.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ protected EventArgs GetDefaultForEventArgType(Type type)
1212
{
1313
if (type == typeof(EventArgs)) return EventArgs.Empty;
1414

15-
var defaultConstructor = GetPublicDefaultConstructor(type) ?? GetNonPublicDefaultConstructor(type);
15+
var defaultConstructor = GetPublicDefaultConstructor(type) ?? GetInternalDefaultConstructor(type);
1616
if (defaultConstructor is null)
1717
{
1818
var message = string.Format(
@@ -24,10 +24,19 @@ protected EventArgs GetDefaultForEventArgType(Type type)
2424
return (EventArgs)defaultConstructor.Invoke([]);
2525
}
2626

27+
private static ConstructorInfo? GetInternalDefaultConstructor(Type type)
28+
{
29+
var nonPublicDefaultConstructor = GetNonPublicDefaultConstructor(type);
30+
var isInternalDefaultConstructor = nonPublicDefaultConstructor?.IsAssembly == true;
31+
return isInternalDefaultConstructor ? nonPublicDefaultConstructor : null;
32+
}
33+
2734
private static ConstructorInfo? GetPublicDefaultConstructor(Type type)
2835
=> GetDefaultConstructor(type, BindingFlags.Public);
36+
2937
private static ConstructorInfo? GetNonPublicDefaultConstructor(Type type)
3038
=> GetDefaultConstructor(type, BindingFlags.NonPublic);
39+
3140
private static ConstructorInfo? GetDefaultConstructor(Type type, BindingFlags bindingFlags)
3241
=> type.GetConstructor(
3342
BindingFlags.Instance | BindingFlags.ExactBinding | bindingFlags, null, Type.EmptyTypes, null);

tests/NSubstitute.Acceptance.Specs/EventRaising.cs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -299,17 +299,28 @@ public void Raise_custom_event_that_has_sender_and_args_but_does_not_inherit_fro
299299
}
300300

301301
[Test]
302-
public void MyEvent_With_CustomEventArgsWithNonPublicDefaultConstructor_IsRaised()
302+
public void MyEvent_with_CustomEventArgsWithInternalDefaultConstructor_is_raised()
303303
{
304304
// Arrange
305-
IExample mockExample = Substitute.For<IExample>();
306-
var consumer = new Consumer(mockExample);
305+
var exampleInternalMock = Substitute.For<IExampleInternal>();
306+
var consumerInternal = new ConsumerInternal(exampleInternalMock);
307307

308308
// Act
309-
mockExample.MyEvent += Raise.EventWith<CustomEventArgsWithInternalDefaultConstructor>(this, null!);
309+
exampleInternalMock.MyEvent += Raise.EventWith<CustomEventArgsWithInternalDefaultConstructor>(this, null!);
310310

311311
// Assert
312-
Assert.That(consumer.SomethingWasDone);
312+
Assert.That(consumerInternal.SomethingWasDone);
313+
}
314+
315+
[Test]
316+
public void MyEvent_with_CustomEventArgsWithPrivateDefaultConstructor_throws_CannotCreateEventArgsException()
317+
{
318+
// Arrange
319+
var examplePrivateMock = Substitute.For<IExamplePrivate>();
320+
321+
// Act and Assert
322+
Assert.Throws<CannotCreateEventArgsException>(() =>
323+
examplePrivateMock.MyEvent += Raise.EventWith<CustomEventArgsWithPrivateDefaultConstructor>(this, null!));
313324
}
314325

315326
class RaisedEventRecorder<T>
@@ -358,13 +369,13 @@ public class CustomEventArgsWithInternalDefaultConstructor : EventArgs
358369
{
359370
internal CustomEventArgsWithInternalDefaultConstructor() { }
360371
}
361-
public interface IExample
372+
public interface IExampleInternal
362373
{
363374
public event EventHandler<CustomEventArgsWithInternalDefaultConstructor> MyEvent;
364375
}
365-
public class Consumer
376+
public class ConsumerInternal
366377
{
367-
public Consumer(IExample example)
378+
public ConsumerInternal(IExampleInternal example)
368379
{
369380
example.MyEvent += OnMyEvent;
370381
}
@@ -378,4 +389,13 @@ private void DoSomething()
378389
SomethingWasDone = true;
379390
}
380391
}
392+
393+
public class CustomEventArgsWithPrivateDefaultConstructor : EventArgs
394+
{
395+
private CustomEventArgsWithPrivateDefaultConstructor() { }
396+
}
397+
public interface IExamplePrivate
398+
{
399+
public event EventHandler<CustomEventArgsWithPrivateDefaultConstructor> MyEvent;
400+
}
381401
}

0 commit comments

Comments
 (0)