We're working on an API for some hardware and I'm trying to write some tests for it in C#. try-catch blocks for repetitive tasks were making my code bloated and repetitive so for getters I was able to wrap like this:
TestGetter(Func<int> method, double expectedVal)
{
int testMe = 0;
try
{
testMe = method();
PassIfTrue(testMe == expectedVal);
}
catch (Exception e)
{
Fail(e.Message);
}
}
So I query the hardware for some known value and compare. I can call with:
TestGetter( () => myAPI.Firmware.Version, 24); //Or whatever.
Which works quite well. But I'm not sure how to do the same with setters. Ie to ensure that the API actually set a value (and doesn't timeout or whatever when I try to set). I'd like to pass the setter to the test method and invoke it in there.
Bonus question: Is there a way to do this with a generic type? There are some custom types defined in the API and I'm not sure of a good way to write these test wrappers for them without writing a new overloaded method for every type. Thanks for any and all help!
You could pass the getter and the setter to the function:
void TestSetter<T>(Func<T> getter, Action<T> setter, T value)
{
try
{
setter(value);
PassIfTrue(EqualityComparer<T>.Default.Equals(getter(), value));
}
catch (Exception e)
{
Fail(e.Message);
}
}
This sets the value, then gets it and compares to the value passed to the setter.
You'd have to call it like:
TestSetter(() => myAPI.Firmware.Version, v => myAPI.Firmware.Version = v, 24);
You can make them generic like Reeds, but you need to use different comparison methods:
public static void TestGetter<T>(Func<T> method, T expectedVal)
{
try
{
T actual = method();
PassIfTrue(expectedVal.Equals(actual));
}
catch (Exception ex)
{
Fail(ex.Message);
}
}
public static void TestSetter<T>(Action setMethod, Func<T> getMethod, T expectedVal)
{
try
{
setMethod();
T actual = getMethod();
PassIfTrue(expectedVal.Equals(actual));
}
catch (Exception ex)
{
Fail(ex.Message);
}
}
You could also pass in a Comparer action to test them if you don't think the Equals method would work for the expected types.
Related
I'm working on a method which uses reflection to call another method. That "other method" can, however, throw an exception and I'd like to propagate that exception with it's original stack information and InnerException. That is simply because the method that uses reflection is not supposed to handle the exception, the caller should.
Here's a simplified version of the code:
public static bool Test() {
try {
return (bool) typeof(Program).GetMethod("OtherMethod").Invoke(null, null);
} catch(TargetInvocationException ex) {
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
}
}
public static bool OtherMethod() {
throw new InvalidOperationException();
}
That code obviously won't compile, since the Test method (according to the compiler) doesn't always return a value.
I could add a return false after the ExceptionDispatchInfo.Capture but I was wondering if there's a nicer way of achieving the same thing. Without writing the redundant return false.
I know it's kind of a nitpick question, but I can't help wondering. Plus, redundant code gives me an itch :P
There is one other option: instead of adding a redundant return false; you could add a redundant throw;.
You then don't need to make up a return value. (OK, not a big deal for a bool)
The simplest solution that doesn't give you redundant or duplicated code is to only put things inside your try that are actually going to throw. Creating your bool, assigning it false and returning it are all "safe" operations, so leave them outside the try.
public static bool Test()
{
bool returnValueOfInvoke = false;
try
{
returnValueOfInvoke = (bool)typeof(Program).GetMethod("OtherMethod").Invoke(null, null);
}
catch(TargetInvocationException ex)
{
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
}
return returnValueOfInvoke;
}
public static void OtherMethod()
{
throw new InvalidOperationException();
}
I want to do extension method to all method for try-catch. In following You can see code block - but it doesn't work
public static class TryCatchExtention
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static void WithTryCatch(this MethodBase method)
{
try
{
//method.Invoke();
}
catch (Exception ex)
{
log.Error("Error : {0} " + ex.Message);
throw new ApplicationException("");
}
}
}
Declare it like that:
public static class TryCatchExtention
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static void WithTryCatch(this object theClass, Action theMethod)
{
try
{
theMethod.Invoke();
}
catch (Exception ex)
{
log.Error("Error : {0} " + ex.Message);
throw new ApplicationException("");
}
}
}
Usage:
var yourClass = new YourClass();
//Pass here the method to be wrapped with a `try-catch` block
yourClass.WithTryCatch(this.YourMethod);}
Or with params:
yourClass.WithTryCatch(()=> this.YourMethod(params...));}
Notice:
This extension method extends any class object and only supports the Action delegate which:
Encapsulates a method that has no parameters and does not return a
value.
You can always support more overloads for more delegates signatures.
Yes you can.
In your example your extension method will be available when you're working with MethodBaseinstances, in other words, when using reflection (the metadata representation of methods and constructors).
On the other hand, if you want that extension method to be always available you should extend the object class.
Nevertheless do not get confused about the difference between extension methods and aspect oriented programming. If what you want is to make a kind of an interceptor to all method calls then i'd suggest you to see what aspect frameworks are available.
I'm not used to that kind of programming so i can't really advise you
I created a method to abstract try/catch functionality. I have about 30 methods that have this exact same try/catch scenario. So I put it in one method:
private T Invoke<T>(Func<T> func)
{
try
{
return func.Invoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
Now, most of the methods call it like this:
public IEnumerable<PingResponse> GetAllForPingRequest(PingRequest pingRequest)
{
return Invoke(() => PingResponseLogic.GetAllForPingRequest(pingRequest));
}
My issue is that I have just a couple of methods that call it without needing to return a value:
Invoke<void>(() => CustomVariableGroupLogic.Delete(customVariableGroup));
However, I can't use void there. The Invoke() method takes a func, but in this case it needs to be an action. I did some research and it looks like I may have to create another Invoke() method, but have it take an action. Those suggestions were from 2009 and 2010 though. Is it possible to somehow use my func method without having to create another Invoke() method like Invoke2()?
One quick and dirty solution would be to add default value after calling Delete method. It will be ignored anyway, if you don't assign result of the Invoke method to a variable. For instance, next code demonstrates this:
Invoke(() => {CustomVariableGroupLogic.Delete(customVariableGroup); return 0; });
You can see similar example proposed here,
If you have lots and lots of such calls, you can build a fancy wrapper, that will return Func for a given Action. Example:
Func<Action, Func<int>> wrap = action => () => {action(); return 0;};
now you can
Invoke(() => wrap(() => CustomVariableGroupLogic.Delete(customVariableGroup)));
but this goes a little bit close to lambda craziness
Inspired by pcm2:
you can create an overload to Invoke, that simply takes Action as a parameter, use solution proposed above to call implementation with Func<T>:
public void Invoke(Action action)
{
Invoke(() => {action(); return 0;});
}
now you simply can
Invoke(() => CustomVariableGroupLogic.Delete(customVariableGroup));
Could you not just create an overload of invoke?
public void Invoke<T>(Func<T> func){
return (T) InvokeInternal(func);
}
public void Invoke(Action action){
InvokeInternal(action);
}
If you'd then want both methods to do the exact same thing, and keeping things DRY, you could create a method like so:
private object InvokeInternal(System.Delegate #delegate)
{
try
{
return #delegate.DynamicInvoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
And have both your overloads calling this method, appropriately casting the result, if any
Do you really have to func.Invoke()? Why not just func()?
Why isn't your Invoke static?
Depending on what LogAndThrowFaultException is doing, this could be pretty bad. Make sure that the exception stack is preserved by always setting the inner exception to ex.
But yes, you need a second function that returns void instead of T.
You can wrap the action into a func like so. Or you can create a convenience function that does the wrapping:
void Main()
{
Action<string> a = s => Console.WriteLine(s);
Invoke(() => { a(); return null; });
Invoke(s);
}
private void Invoke(Action a)
{
Invoke(() => { a(); return null; };
}
Is there any way to dynamically intercept method calls in a class in C#, equivalent to the Perl AUTOLOAD mechanism?
Case in point, I have a helper class with a 'core' method that writes to the system Event Log and a couple of convenience overloads to simplify the most common uses.
Now, I am seeing an emerging code pattern where I use try ... catch to attempt to write an entry, but ignore any failures that are related to the actual event log handling. For instance when trying to log an application exception when the event log is full, I want the application to crash with the "real" application exception, not the "event log" exception.
I have currently just created a new set of overloads that encapsulates this, but what I would really like to do is have dynamic handling of these methods, i.e. any method call to a method name starting with "Try" calls the respective "real" method, encapsulated in a try .. catch. This is would be so easy in Perl ;-) but can it even be done in C#?
Some code that might simplify the explanation:
public class SomeClass
{
// Core functionality
public static void WriteToLog(string message, EventLogEntryType type)
{
...
}
// Overloaded methods for common uses
public static void WriteToLog(SomeObject obj)
{
WriteToLog(obj.ToString(), EventLogEntryType.Information);
}
public static void WriteToLog(SomeException ex)
{
WriteToLog(ex.Message, EventLogEntryType.Error);
}
// Additional wrappers that ignores errors
// These are what I'd like to handle dynamically instead of manually:
public static void TryWriteToLog(SomeObject obj)
{
try
{
WriteToLog(obj);
}
catch (Exception logException)
{
Console.WriteLine(logException.Message);
}
}
public static void TryWriteToLog(SomeException ex)
{
try
{
WriteToLog(ex);
}
catch (Exception logException)
{
Console.WriteLine(logException.Message);
}
}
}
Oh...
Much to my surprise, I figured it out over a cup of coffee and it actually works. To paraphrase the initial code snippet, here's what I did:
using System;
using System.Dynamic;
using System.Reflection;
public class SomeClass : DynamicObject
{
// Core functionality
public static void WriteToLog(string message, EventLogEntryType type)
{
...
}
// Overloaded methods for common uses
public static void WriteToLog(SomeObject obj)
{
WriteToLog(obj.ToString(), EventLogEntryType.Information);
}
public static void WriteToLog(SomeException ex)
{
WriteToLog(ex.Message, EventLogEntryType.Error);
}
// Redirect all method calls that start with 'Try' to corresponding normal
// methods, but encapsulate the method call in a try ... catch to ignore
// log-related errors
private static dynamic instance = new SomeClass();
public static dynamic Instance { get { return instance; } }
public override bool TryInvokeMember(InvokeMemberBinder binder,
object[] args,
out object result)
{
if (binder.Name.StartsWith("Try"))
{
try
{
result = this.GetType().InvokeMember(binder.Name.Substring(3),
BindingFlags.InvokeMethod,
null,
this,
args);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.Message);
result = null;
}
return true;
}
else
{
return base.TryInvokeMember(binder, args, out result);
}
}
The following methods can now be invoked, and seems to work as intended:
SomeClass.Instance.WriteToLog(SomeObject obj)
SomeClass.Instance.TryWriteToLog(SomeObject obj)
SomeClass.Instance.WriteToLog(SomeException ex)
SomeClass.Instance.TryWriteToLog(SomeException ex)
SomeClass.Instance.WriteToLog(string message, EventLogEntryType type)
SomeClass.Instance.TryWriteToLog(string message, EventLogEntryType type)
Small caveat: The above code is cleaned up for posting on an official forum, it might not work out of the box.
I have two functions that have different enough logic but pretty much the same exception handling:
public void DoIt1 // DoIt2 has different logic but same exception handling
{
try
... DoIt1 logic
catch (MySpecialException myEx)
{
Debug.WriteLine(myEx.MyErrorString);
throw;
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
throw;
}
}
It is not possible to use a single entry point for DoIt1 and DoIt2, because they are called in from outside.
Is Copy/Pase (for the exception block) the best approach?
It depends... if there is that much commonality, you could pass in the thing to do as a parameter - either as an interface or a delegate:
void Foo(Action thingToDo) {
if(thingToDo == null) throw new ArgumentNullException("thingToDo");
try {
thingToDo();
} catch {...} // lots of
}
And call as:
Foo(delegate { /* logic A */ });
Foo(delegate { /* logic B */ });
Try:
public static class Catching<TException> where TException : Exception
{
public static bool Try<T>(Func<T> func, out T result)
{
try
{
result = func();
return true;
}
catch (TException x)
{
// log exception message (with call stacks
// and all InnerExceptions)
}
result = default(T);
return false;
}
public static T Try<T>(Func<T> func, T defaultValue)
{
T result;
if (Try(func, out result))
return result;
return defaultValue;
}
}
Example:
int queueSize = Catching<MyParsingException>
.Try(() => Parse(optionStr, "QueueSize"), 5);
If Parse throws a MyParsingException, queueSize will default to 5, otherwise the returned value from Parse is used (or any other exception will propagate normally, which is usually what you want with an unexpected exception).
This helps to avoid breaking up the flow of the code, and also centralises your logging policy.
You can write specialised versions of this kind of exception wrapping for special cases, e.g. catching a particular set of three exceptions, or whatever.
For the extreme end of the spectrum of possible solutions, check out Aspect-Oriented-Programming techniques, and tools such as PostSharp or Microsoft Policy Injection Block. This way you can define an aspect that does something on exception and weave it into all places in your code that need it.
If you just want to log the exceptions' messages and items, without doing special processing in the catch block, you could create a Reflection-based Object logger, passing the Exception as an argument. Doing so, you don't have a lot of catch blocks.
And if you are the code's owner, you can put the logging procedure inside the MySpecialException's constructor, removing the catch's block and making the code cleaner.
You could have something like:
public static class ErrorHandler
{
public static void HandleMyException(MyException myEx)
{
Debug.WriteLine(myEx.MyErrorString);
throw;
}
public static void HandleException(Exception myEx)
{
Debug.WriteLine(e.ToString());
throw;
}
}
or, in this specific case, have a more generic function like:
public static class ErrorHandler
{
public static void WriteAndThrow(string msg)
{
Debug.WriteLine(msg);
throw;
}
}