i am using this code
//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Reflection;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
new Program().DoTest();
}
public void DoTest()
{
var a = LoggingAdvice<asd>.Create(new a());
a.targetMethod("nadeem", 123, null);
}
}
public class LoggingAdvice<T> : DispatchProxy
{
private T _decorated;
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
var result = targetMethod.Invoke(_decorated, args);
var resultTask = result as Task;
return result;
}
public static T Create(T decorated)
{
object proxy = Create<T, LoggingAdvice<T>>();
((LoggingAdvice<T>)proxy).SetParameters(decorated);
return (T)proxy;
}
private void SetParameters(T decorated)
{
if (decorated == null)
{
throw new ArgumentNullException(nameof(decorated));
}
_decorated = decorated;
}
}
public class asd
{
public asd()
{
}
public int targetMethod(string name, int number, int? count)
{
Console.WriteLine(name);
Console.WriteLine(number);
Console.WriteLine(count.HasValue ? count.Value.ToString() : "NULL");
return 1;
}
}
}
the most important thing about it, is this line of code
var result = targetMethod.Invoke(_decorated, args);
the target method has 3 parameters, one of them is nullable integer as the following
public int targetMethod(string name, int number, int? count)
the args that is getting passed to Invoke method has the following values as you can view it in the visual studio debugging mode:
["nadeem", 123, (null)]
the invoke is raising an exception that i cannot convert string to nullable integer.
how i can avoid this type of issue, note that i am not sure which function i am going to be invoked, i would only know it on runtime.
Currently i've got this code:
private async Task<bool> IsMentionedInDisposeCallAsync(SyntaxNodeAnalysisContext context, FieldDeclarationSyntax fieldDeclarationSyntax)
{
foreach (var variableDeclaratorSyntax in fieldDeclarationSyntax.Declaration.Variables)
{
var declaredSymbol = context.SemanticModel.GetDeclaredSymbol(variableDeclaratorSyntax);
if (declaredSymbol is IFieldSymbol fieldSymbol)
{
// SymbolFinder.FindReferencesAsync()
var b = fieldSymbol.Locations;
// context.SemanticModel.Compilation.
}
}
return false;
}
And this scenario:
private static readonly string TestSourceImplementsDisposableAndDoesMentionDisposableField = #"
using System;
using System.IO;
namespace ConsoleApplication1
{
public class SampleDisposable : IDisposable
{
public void Dispose()
{
}
}
public class SampleConsumer : IDisposable
{
private SampleDisposable _disposable = new SampleDisposable();
private IDisposable _ms = new MemoryStream();
public void Dispose()
{
_disposable?.Dispose();
_ms?.Dispose();
}
}
}";
Ultimately my desire is to figure out whether a dispose method is accessing a disposable field. Unfortunately i can't seem to find a way to get this working without using SymbolFinder, which requires a solution.
I did something similar with SymbolFinder and it was an easy thing to do - but how do i do it from the functionality available within a diagnostic?
Am i missing something obvious here?
You could simply use the SemanticModel to analyse the type used for the field like this:
private async Task<bool> IsMentionedInDisposeCallAsync(SyntaxNodeAnalysisContext context, FieldDeclarationSyntax fieldDeclarationSyntax)
{
foreach (var variableDeclaratorSyntax in fieldDeclarationSyntax.Declaration.Variables)
{
var declaredSymbol = context.SemanticModel.GetDeclaredSymbol(variableDeclaratorSyntax);
if (declaredSymbol is IFieldSymbol fieldSymbol)
{
var isDisposeable = CheckIsTypeIDisposeable(fieldSymbol.Type as INamedTypeSymbol);
// SymbolFinder.FindReferencesAsync()
var b = fieldSymbol.Locations;
// context.SemanticModel.Compilation.
}
}
return false;
}
private string fullQualifiedAssemblyNameOfIDisposeable = typeof(IDisposable).AssemblyQualifiedName;
private bool CheckIsTypeIDisposeable(INamedTypeSymbol type)
{
// Identify the IDisposable class. You can use any method to do this here
// A type.ToDisplayString() == "System.IDisposable" might do it for you
if(fullQualifiedAssemblyNameOfIDisposeable ==
type.ToDisplayString() + ", " + type.ContainingAssembly.ToDisplayString())
{
return true;
}
if(type.BaseType != null)
{
if (CheckIsTypeIDisposeable(type.BaseType))
{
return true;
}
}
foreach(var #interface in type.AllInterfaces)
{
if (CheckIsTypeIDisposeable(#interface))
{
return true;
}
}
return false;
}
Basically you would search through all interfaces of the class and the base class recursively to find the type corresponding to IDisposeable - which should be somewhere in the hierarchy.
I'm working on a code base which has the purpose to format code. In some instances, I have to remove syntax tokens such as the keyword "params" inside the parameter list if I found one and it's redundant or remove some unneeded braces ( "{" "}").
The thing is, it's so hard and uneasy to remove syntax token from the syntax tree. I have tried many different solutions that you can find below, but for the life of me, I cannot succeed. I'd like a solution that could work for any syntax token U might encounter and that I need to possibly remove from the syntax tree.
In the following case, I have built an analyzer that is currently functionnal but the code fix provider is not quite working... (It's a case of redundant params keyword usage).
//UPDATE - I have provided full code of Analyzer/Code fix provider / NUnit tests
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Formatting;
namespace RefactoringEssentials.CSharp.Diagnostics
{
[ExportCodeFixProvider(LanguageNames.CSharp), System.Composition.Shared]
public class RedundantParamsCodeFixProvider : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
{
get
{
return ImmutableArray.Create(CSharpDiagnosticIDs.RedundantParamsAnalyzerID);
}
}
public override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;
var span = context.Span;
var diagnostics = context.Diagnostics;
var root = await document.GetSyntaxRootAsync(cancellationToken);
var diagnostic = diagnostics.First();
var node = root.FindNode(context.Span) as ParameterSyntax;
if (node == null)
return;
if (!node.Modifiers.Any(x => x.IsKind(SyntaxKind.ParamsKeyword)))
return;
var oldParameterNode = node;
var paramList = node.Parent as ParameterListSyntax;
if (paramList == null)
return;
//var newRoot = root.ReplaceNode(
// oldParameterNode.Parent as ParameterListSyntax,
// paramList.WithParameters
// (SyntaxFactory.SeparatedList(paramList.Parameters.ToArray()))
// .WithLeadingTrivia(node.GetLeadingTrivia())
// .WithTrailingTrivia(node.GetTrailingTrivia()))
// .WithAdditionalAnnotations(Formatter.Annotation);
//var paramsKeyword = (node.Modifiers.FirstOrDefault(x => x.IsKind(SyntaxKind.ParamsKeyword)));
//var indexParams = node.Modifiers.IndexOf(paramsKeyword);
//var syntaxListWithoutParams = node.Modifiers.RemoveAt(indexParams);
//node.ReplaceToken(paramsKeyword, syntaxListWithoutParams.AsEnumerable());
context.RegisterCodeFix(CodeActionFactory.Create(node.Span, diagnostic.Severity, "Remove 'params' modifier", token =>
{
var newNode = SyntaxFactory.Parameter(node.AttributeLists,node.Modifiers.Remove(SyntaxFactory.Token(SyntaxKind.ParamsKeyword)),node.Type,node.Identifier,node.Default);
var newRoot = root.ReplaceNode(node, newNode);
return Task.FromResult(document.WithSyntaxRoot(newRoot));
}), diagnostic);
//context.RegisterCodeFix(CodeActionFactory.Create(node.SKCpan, diagnostic.Severity, , document.WithSyntaxRoot(newRoot)), diagnostic);
}
}
}
This is the use cases in my situation.
using System;
using NUnit.Framework;
using RefactoringEssentials.CSharp.Diagnostics;
namespace RefactoringEssentials.Tests.CSharp.Diagnostics
{
[TestFixture]
public class RedundantParamsTests : CSharpDiagnosticTestBase
{
[Test]
public void TestBasicCase()
{
Analyze<RedundantParamsAnalyzer>(#"class FooBar
{
public virtual void Foo(string fmt, object[] args)
{
}
}
class FooBar2 : FooBar
{
public override void Foo(string fmt, $params object[] args$)
{
System.Console.WriteLine(fmt, args);
}
}", #"class FooBar
{
public virtual void Foo(string fmt, object[] args)
{
}
}
class FooBar2 : FooBar
{
public override void Foo(string fmt, object[] args)
{
System.Console.WriteLine(fmt, args);
}
}");
}
[Test]
public void TestValidCase()
{
Analyze<RedundantParamsAnalyzer>(#"class FooBar
{
public virtual void Foo(string fmt, object[] args)
{
}
}
class FooBar2 : FooBar
{
public override void Foo(string fmt, object[] args)
{
System.Console.WriteLine(fmt, args);
}
}");
}
[Test]
public void ValideParamsUsageTests()
{
Analyze<RedundantParamsAnalyzer>(#"class FooBar
{
public virtual void Foo(string fmt, params object[] args)
{
}
}
class FooBar2 : FooBar
{
public override void Foo(string fmt, params object[] args)
{
System.Console.WriteLine(fmt, args);
}
}");
}
[Test]
public void TestDisable()
{
Analyze<RedundantParamsAnalyzer>(#"class FooBar
{
public virtual void Foo(string fmt, object[] args)
{
}
}
class FooBar2 : FooBar
{
// ReSharper disable once RedundantParams
public override void Foo(string fmt, params object[] args)
{
System.Console.WriteLine(fmt, args);
}
}");
}
}
}
For those who might be interested in how I determine that the params is redundant, here's the logic:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
using System.Linq;
namespace RefactoringEssentials.CSharp.Diagnostics
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class RedundantParamsAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor descriptor = new DiagnosticDescriptor(
CSharpDiagnosticIDs.RedundantParamsAnalyzerID,
GettextCatalog.GetString("'params' is ignored on overrides"),
GettextCatalog.GetString("'params' is always ignored in overrides"),
DiagnosticAnalyzerCategories.RedundanciesInDeclarations,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: HelpLink.CreateFor(CSharpDiagnosticIDs.RedundantParamsAnalyzerID),
customTags: DiagnosticCustomTags.Unnecessary
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(
(nodeContext) =>
{
Diagnostic diagnostic;
if (TryGetParamsDiagnostic(nodeContext, out diagnostic))
{
nodeContext.ReportDiagnostic(diagnostic);
}
},
SyntaxKind.ParameterList
);
}
//I think it's a better decision to head in this direction instead of MethodDeclaration.
private static bool TryGetParamsDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic)
{
diagnostic = default(Diagnostic);
if (nodeContext.IsFromGeneratedCode())
return false;
var paramList = nodeContext.Node as ParameterListSyntax;
var declaration = paramList?.Parent as MethodDeclarationSyntax;
if (declaration == null)
return false;
if (declaration.Modifiers.Count == 0 || !declaration.Modifiers.Any(SyntaxKind.OverrideKeyword))
return false;
var lastParam = declaration.ParameterList.Parameters.LastOrDefault();
SyntaxToken? paramsModifierToken = null;
if (lastParam == null)
return false;
foreach (var x in lastParam.Modifiers)
{
if (x.IsKind(SyntaxKind.ParamsKeyword))
{
paramsModifierToken = x;
break;
}
}
if (!paramsModifierToken.HasValue ||
!paramsModifierToken.Value.IsKind(SyntaxKind.ParamsKeyword))
return false;
diagnostic = Diagnostic.Create(descriptor, lastParam.GetLocation());
return true;
}
}
In this case, you don't want to remove the whole node, rather you just want to remove the params modifier. Since SyntaxNodes are immutable, you need to create a new node with the appropriate modifiers using the WithModifiers method:
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var diagnostic = context.Diagnostics.First();
context.RegisterCodeFix(CodeAction.Create("Remove 'params' modifier", async token =>
{
var document = context.Document;
var root = await document.GetSyntaxRootAsync(token);
var fullParameterNode = root.FindNode(diagnostic.Location.SourceSpan, false) as ParameterSyntax;
// Keep all modifiers except the params
var newModifiers = fullParameterNode.Modifiers.Where(m => !m.IsKind(SyntaxKind.ParamsKeyword));
var syntaxModifiers = SyntaxTokenList.Create(new SyntaxToken());
syntaxModifiers.AddRange(newModifiers);
var updatedParameterNode = fullParameterNode.WithModifiers(syntaxModifiers);
var newDoc = document.WithSyntaxRoot(root.ReplaceNode(fullParameterNode, updatedParameterNode));
return newDoc;
}, "KEY"), diagnostic);
}
As for a generic remove option for syntax, I don't know of one that is easy to use. The Node.ReplaceSyntax is a rather complicated method and I usually find it easier to work with the ReplaceNode or RemoveNode methods.
Is there any way to pass generic types using a TestCase to a test in NUnit?
This is what I would like to do but the syntax is not correct...
[Test]
[TestCase<IMyInterface, MyConcreteClass>]
public void MyMethod_GenericCall_MakesGenericCall<TInterface, TConcreteClass>()
{
// Arrange
// Act
var response = MyClassUnderTest.MyMethod<TInterface>();
// Assert
Assert.IsInstanceOf<TConcreteClass>(response);
}
Or if not, what is the best way to achieve the same functionality (obviously I'll have multiple TestCases in the real code)?
Update with another example...
Here is another example with a single generic type passed...
[Test]
[TestCase<MyClass>("Some response")]
public void MyMethod_GenericCall_MakesGenericCall<T>(string expectedResponse)
{
// Arrange
// Act
var response = MyClassUnderTest.MyMethod<T>();
// Assert
Assert.AreEqual(expectedResponse, response);
}
NUnit test methods actually can be generic as long as the generic type arguments can be inferred from parameters:
[TestCase(42)]
[TestCase("string")]
[TestCase(double.Epsilon)]
public void GenericTest<T>(T instance)
{
Console.WriteLine(instance);
}
If the generic arguments cannot be inferred, the test runner will not have a clue how to resolve type arguments:
[TestCase(42)]
[TestCase("string")]
[TestCase(double.Epsilon)]
public void GenericTest<T>(object instance)
{
Console.WriteLine(instance);
}
But for this case you can implement a custom attribute:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TestCaseGenericAttribute : TestCaseAttribute, ITestBuilder
{
public TestCaseGenericAttribute(params object[] arguments)
: base(arguments)
{
}
public Type[] TypeArguments { get; set; }
IEnumerable<TestMethod> ITestBuilder.BuildFrom(IMethodInfo method, Test suite)
{
if (!method.IsGenericMethodDefinition)
return base.BuildFrom(method, suite);
if (TypeArguments == null || TypeArguments.Length != method.GetGenericArguments().Length)
{
var parms = new TestCaseParameters { RunState = RunState.NotRunnable };
parms.Properties.Set(PropertyNames.SkipReason, $"{nameof(TypeArguments)} should have {method.GetGenericArguments().Length} elements");
return new[] { new NUnitTestCaseBuilder().BuildTestMethod(method, suite, parms) };
}
var genMethod = method.MakeGenericMethod(TypeArguments);
return base.BuildFrom(genMethod, suite);
}
}
Usage:
[TestCaseGeneric("Some response", TypeArguments = new[] { typeof(IMyInterface), typeof(MyConcreteClass) }]
public void MyMethod_GenericCall_MakesGenericCall<T1, T2>(string expectedResponse)
{
// whatever
}
And a similar customization for TestCaseSourceAttribute:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TestCaseSourceGenericAttribute : TestCaseSourceAttribute, ITestBuilder
{
public TestCaseSourceGenericAttribute(string sourceName)
: base(sourceName)
{
}
public Type[] TypeArguments { get; set; }
IEnumerable<TestMethod> ITestBuilder.BuildFrom(IMethodInfo method, Test suite)
{
if (!method.IsGenericMethodDefinition)
return base.BuildFrom(method, suite);
if (TypeArguments == null || TypeArguments.Length != method.GetGenericArguments().Length)
{
var parms = new TestCaseParameters { RunState = RunState.NotRunnable };
parms.Properties.Set(PropertyNames.SkipReason, $"{nameof(TypeArguments)} should have {method.GetGenericArguments().Length} elements");
return new[] { new NUnitTestCaseBuilder().BuildTestMethod(method, suite, parms) };
}
var genMethod = method.MakeGenericMethod(TypeArguments);
return base.BuildFrom(genMethod, suite);
}
}
Usage:
[TestCaseSourceGeneric(nameof(mySource)), TypeArguments = new[] { typeof(IMyInterface), typeof(MyConcreteClass) }]
Update for C# 11.0:
Starting with C# 11.0 you can specify generic attributes. This makes possible to use generic [TestCase<...>] attributes exactly the same way as the OP wanted:
// Requires C# 11.
// For exactly one type argument. See the base implementation above.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TestCaseAttribute<T> : TestCaseGenericAttribute
{
public TestCaseAttribute(params object[] arguments)
: base(arguments) => TypeArguments = new[] { typeof(T) };
}
// For exactly two type arguments. See the base implementation above.
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TestCaseAttribute<T1, T2> : TestCaseGenericAttribute
{
public TestCaseAttribute(params object[] arguments)
: base(arguments) => TypeArguments = new[] { typeof(T1), typeof(T2) };
}
// You can add more classes to support more type arguments or
// to create specialized [TestCaseSource<...>] attributes the same way.
So finally, this is now supported:
[TestCase<IMyInterface, MyConcreteClass>("Some response")]
public void MyMethod_GenericCall_MakesGenericCall<T1, T2>(string expectedResponse)
{
// whatever
}
I had occasion to do something similar today, and wasn't happy with using reflection.
I decided to leverage [TestCaseSource] instead by delegating the test logic as a test context to a generic testing class, pinned on a non-generic interface, and called the interface from individual tests (my real tests have many more methods in the interface, and use AutoFixture to set up the context):
class Sut<T>
{
public string ReverseName()
{
return new string(typeof(T).Name.Reverse().ToArray());
}
}
[TestFixture]
class TestingGenerics
{
public static IEnumerable<ITester> TestCases()
{
yield return new Tester<string> { Expectation = "gnirtS"};
yield return new Tester<int> { Expectation = "23tnI" };
yield return new Tester<List<string>> { Expectation = "1`tsiL" };
}
[TestCaseSource("TestCases")]
public void TestReverse(ITester tester)
{
tester.TestReverse();
}
public interface ITester
{
void TestReverse();
}
public class Tester<T> : ITester
{
private Sut<T> _sut;
public string Expectation { get; set; }
public Tester()
{
_sut=new Sut<T>();
}
public void TestReverse()
{
Assert.AreEqual(Expectation,_sut.ReverseName());
}
}
}
You can make custom GenericTestCaseAttribute
[Test]
[GenericTestCase(typeof(MyClass) ,"Some response", TestName = "Test1")]
[GenericTestCase(typeof(MyClass1) ,"Some response", TestName = "Test2")]
public void MapWithInitTest<T>(string expectedResponse)
{
// Arrange
// Act
var response = MyClassUnderTest.MyMethod<T>();
// Assert
Assert.AreEqual(expectedResponse, response);
}
Here is implementation of GenericTestCaseAttribute
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class GenericTestCaseAttribute : TestCaseAttribute, ITestBuilder
{
private readonly Type _type;
public GenericTestCaseAttribute(Type type, params object[] arguments) : base(arguments)
{
_type = type;
}
IEnumerable<TestMethod> ITestBuilder.BuildFrom(IMethodInfo method, Test suite)
{
if (method.IsGenericMethodDefinition && _type != null)
{
var gm = method.MakeGenericMethod(_type);
return BuildFrom(gm, suite);
}
return BuildFrom(method, suite);
}
}
Attributes in C# cannot be generic, so you won't be able to do things exactly as you'd like. Perhaps the easiest thing would be to put TestCase attributes onto a helper method which uses reflection to call the real method. Something like this might work (note, untested):
[TestCase(typeof(MyClass), "SomeResponse")]
public void TestWrapper(Type t, string s)
{
typeof(MyClassUnderTest).GetMethod("MyMethod_GenericCall_MakesGenericCall").MakeGenericMethod(t).Invoke(null, new [] { s });
}
Start with the test first--even when testing. What do you want to do? Probably something like this:
[Test]
public void Test_GenericCalls()
{
MyMethod_GenericCall_MakesGenericCall<int>("an int response");
MyMethod_GenericCall_MakesGenericCall<string>("a string response");
:
}
Then you can just make your test a plain old function test. No [Test] marker.
public void MyMethod_GenericCall_MakesGenericCall<T>(string expectedResponse)
{
// Arrange
// Act
var response = MyClassUnderTest.MyMethod<T>();
// Assert
Assert.AreEqual(expectedResponse, response);
}
I did something similar last week. Here's what I ended up with:
internal interface ITestRunner
{
void RunTest(object _param, object _expectedValue);
}
internal class TestRunner<T> : ITestRunner
{
public void RunTest(object _param, T _expectedValue)
{
T result = MakeGenericCall<T>();
Assert.AreEqual(_expectedValue, result);
}
public void RunTest(object _param, object _expectedValue)
{
RunTest(_param, (T)_expectedValue);
}
}
And then the test itself:
[Test]
[TestCase(typeof(int), "my param", 20)]
[TestCase(typeof(double), "my param", 123.456789)]
public void TestParse(Type _type, object _param, object _expectedValue)
{
Type runnerType = typeof(TestRunner<>);
var runner = Activator.CreateInstance(runnerType.MakeGenericType(_type));
((ITestRunner)runner).RunTest(_param, _expectedValue);
}
As might be testing with generic functions that return objects?. Example:
public Empleado TestObjetoEmpleado(Empleado objEmpleado)
{
return objEmpleado;
}
Thanks
I slightly modified the TestCaseGenericAttribute somebody posted here:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class GenericTestCaseAttribute : TestCaseAttribute, ITestBuilder
{
public GenericTestCaseAttribute(params object[] arguments)
: base(arguments)
{
}
IEnumerable<TestMethod> ITestBuilder.BuildFrom(IMethodInfo method, Test suite)
{
if (!method.IsGenericMethodDefinition) return base.BuildFrom(method, suite);
var numberOfGenericArguments = method.GetGenericArguments().Length;
var typeArguments = Arguments.Take(numberOfGenericArguments).OfType<Type>().ToArray();
if (typeArguments.Length != numberOfGenericArguments)
{
var parms = new TestCaseParameters { RunState = RunState.NotRunnable };
parms.Properties.Set("_SKIPREASON", $"Arguments should have {typeArguments} type elements");
return new[] { new NUnitTestCaseBuilder().BuildTestMethod(method, suite, parms) };
}
var genMethod = method.MakeGenericMethod(typeArguments);
return new TestCaseAttribute(Arguments.Skip(numberOfGenericArguments).ToArray()).BuildFrom(genMethod, suite);
}
}
This version expects one list of all parameters, starting with the type parameters, starting with the type paramters. Usage:
[Test]
[GenericTestCase(typeof(IMailService), typeof(MailService))]
[GenericTestCase(typeof(ILogger), typeof(Logger))]
public void ValidateResolution<TQuery>(Type type)
{
// arrange
var sut = new AutoFacMapper();
// act
sut.RegisterMappings();
var container = sut.Build();
// assert
var item = sut.Container.Resolve<TQuery>();
Assert.AreEqual(type, item.GetType());
}
I have written my own TestCaseGenericAttribute and TestCaseGenericSourceAttribute.
https://github.com/nunit/nunit/issues/3580
The Conditional Attribute in .NET allows you to disable the invocation of methods at compile time. I am looking for basically the same exact thing, but at run time. I feel like something like this should exist in AOP frameworks, but I don't know the name so I am having trouble figuring out if it is supported.
So as an example I'd like to do something like this
[RuntimeConditional("Bob")]
public static void M() {
Console.WriteLine("Executed Class1.M");
}
//.....
//Determines if a method should execute.
public bool RuntimeConditional(string[] conditions) {
bool shouldExecute = conditions[0] == "Bob";
return shouldExecute;
}
So where ever in code there is a call to the M method, it would first call RuntimeConditional and pass in Bob to determine if M should be executed.
You can actually use PostSharp to do what you want.
Here's a simple example you can use:
[Serializable]
public class RuntimeConditional : OnMethodInvocationAspect
{
private string[] _conditions;
public RuntimeConditional(params string[] conditions)
{
_conditions = conditions;
}
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
if (_conditions[0] == "Bob") // do whatever check you want here
{
eventArgs.Proceed();
}
}
}
Or, since you're just looking at "before" the method executes, you can use the OnMethodBoundaryAspect:
[Serializable]
public class RuntimeConditional : OnMethodBoundaryAspect
{
private string[] _conditions;
public RuntimeConditional(params string[] conditions)
{
_conditions = conditions;
}
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
if (_conditions[0] != "Bob")
{
eventArgs.FlowBehavior = FlowBehavior.Return; // return immediately without executing
}
}
}
If your methods have return values, you can deal with them too. eventArgs has a returnValue property that is settable.
I believe this would be a very simple way of doing what you described:
public static void M()
{
if (RuntimeConditional("Bob"))
{
Console.WriteLine("Executed Class1.M");
}
}
Thanks