Is there any C# equivalent to Perl AUTOLOAD? - c#

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.

Related

Using a setter as a parameter in C#? (Maybe with delegate?)

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.

Return value to another class/object without added a relation between them C#

I having some classes related like the following domain drawing:
The Requestcontroller is running a loop in a ThreadPool, which on received messages will handle them and call some methods in FooClass, which then should throw exceptions if anything goes wrong.
In example (in some way pseudo-code):
class RequestController
{
private FooClass fooClass;
public RequestController(ref FooClass fooClass)
{
this.fooClass = fooClass;
}
void OnResponseReceived()
{
try
{
this.fooClass.ProcessingRequest("id", "requestType", 13);
}
catch(Exception ex)
{
Debug.Fail(ex.Message);
}
}
}
class FooClass
{
private object myObj;
[...]
public void ProcessingRequest(string id, string type, int count)
{
try
{
myObj.MethodAsync(id, type, RequestFailedCB, myObj);
//This method throws an Exception, that I want to be handled by RequestController class based on the Exception
}
catch(Exception)
{
throw;
}
}
}
So, my problem is that the Async method (MethodAsync in FooClass) will fail, and throw an Exception in FooClass, but it's giving me "Unhandle Exception". What I want is that the Requestcontroller is calling the method of FooClass, and if the async method that has been invoked in the FooClass.ProcessingRequest fails and throws an exception, which my RequestController should react on, and sending a message further on in the system, that there has been an error in the response received.
Would it be an idea to make the ProcessingRequest as and Callback method, or are there any better way to solve this purpose???
EDIT:
#KC-NH without posting pages of complex code, I'll try to get closer to the point.
As commented I forgot to mention that the project i .net 4 target. And the example posted in the FooClass method, is actually calling a .BeginTransfer of the UCMA 4 api, which I want to catch if it fails, and let the RequestController send a message about the failure further on in the system. The .BeginTransfer method returns IAsyncResult, and needs a Callback as one of the parameters.
The exception that the system throws, is inside this CB, but if I try to throw that exception from the Callback, I'm getting "Unhandled Exception", probably cuz the callback doesn't know where to throw that exception??
[.NET 4.5 specific solution]
You should always await async calls. await will rethrow exceptions as expected. This should correct your problem:
class RequestController
{
private FooClass fooClass;
public RequestController(ref FooClass fooClass)
{
this.fooClass = fooClass;
}
public async void OnResponseReceived()
{
try
{
await fooClass.ProcessingRequest();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Fail(ex.Message);
}
}
}
public class FooClass
{
private object myObj;
public async Task ProcessingRequest()
{
await myObj.MethodAsync(id, type, RequestFailedCB, myObj);
}
}
I spoke with one of my colleagues today. He suggested that I used an EventHandler, to raise an event on exception catched in the callback method inside my FooClass. So the solution looks like this:
FooClass RequestFailedCB throws an exception
In RequestFailedCB the exception gets catched, and raising a ErrorEvent on my EventHandler.
The RequestController now gets information, that an event has been raised.
The RequestController will handle the error throw by the event, based on EventArgs and sender object, and can now send that error further on in the system.
Problem solved :) Thanks for all inputs.

Can we write extension method for all methods?

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

C# How do I use AOP for static methods?

I have built a c# .net 4.0 library.
all of the methods are public and static.
i want to add an aspect using an aspect programming library that does something like this:
try block
1. call method (if method throws exception)
catch block
2. log the exception and massage the exception
it is a dll (class library project)
can you please advice if there is a way to add try/catch routines in one class instead of wrapping around all methods one by one?
Because you had mentioned word static neither ninject nor castle-windsor nor anything else based upon castle-dynamicproxy would help you, because they able to add aspects around regular method. So you have two options:
Handwritten tracing decorator
Add separate handwritten tracing decorator that will add required functionality without altering of existing code
Benefits
Simple and easy to write yourself
Drawbacks
Almost no call context. This is important for tracing, if you like to know what method actually has been called and what parameters had been passed, etc.
New layer of abstraction around existed code. Instead of calling your static methods, you have to call Decorator that will call your static methods inside
Example
// Decorated calls
TraceDecorator.Aspect(() => StaticLogic.SuccessfulCall());
TraceDecorator.Aspect(() => StaticLogic.ExceptionCall());
TraceDecorator.Aspect(() => StaticLogic.SuccessfulCallWithReturn(42));
TraceDecorator.Aspect(() => StaticLogic.ExceptionCallWithReturn(42));
// Decorator itself
public static class TraceDecorator
{
public static T Aspect<T>(Func<T> func)
{
try
{
return func();
}
catch(Exception ex)
{
LogException(ex);
return default(T);
}
}
public static void Aspect(Action func)
{
try
{
func();
}
catch(Exception ex)
{
LogException(ex);
}
}
private static void LogException(Exception ex)
{
Console.WriteLine("Traced by TraceDecorator: {0}", ex);
}
}
Full sample available here
PostSharp
Take a look at Non-Invasive Tracing & Logging with postsharp
Benefits
Broadcast your aspect without altering existing code or adding attributes by yourself, whatever you found suitable
Separation of concerns: tracing/logging are separated from your logic
and alot more …
Drawbacks
Nothing come for free. But there is a free PostSharp edition available with limited functionality
Sometimes integration with other tools because of post-compilation
See NConcern .NET AOP Framework, an open source project.
Example
Your static class
static public class Calculator
{
static public int Add(int a, int b)
{
return a + b;
}
}
Logger
static public class Logger
{
static public void Log(MethodInfo method, object[] arguments, Exception exception)
{
Console.WriteLine("{0}({1}) exception = {2}", method.Name, string.Join(", ", arguments), exception.Message);
}
}
Aspect : log on exception
public class Logging : IAspect
{
public IEnumerable<IAdvice> Advise(MethodInfo method)
{
yield return Advice.Basic.After.Throwing((instance, arguments, exception) =>
{
Logger.Log(method, arguments, exception);
});
}
}
Joinpoint : methods of Calculator
var calculatorMethods = new Func<MethodInfo, bool>(method => method.ReflectedType == typeof(Calculator));
Activate the logging aspect for joinpoint
Aspect.Weave<Logging>(calculatorMethods);

What is the best way to re-use exception handling logic in C#?

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;
}
}

Categories

Resources