C# Passing a reference to a generic method to another method - c#

I have a program that calls dozens of methods with varying signatures, but the exception handling inside each one is identical. Is there some way to define a method that can accept a reference to a generic method with various signatures (which rules out a Delegate - right?) and return the object, or void that the method requires? I'm using .NET 4.72.
Here is stripped down version of what I'm currently doing and some pseudo-code of what I'd like to do:
static class StackOverflowQuestion
{
public static void Main(string[] args)
{
// What I'm currently doing:
MethodOne("x");
int ret = MethodTwo(0);
//.
//.
//.
MethodNineteen();
// what I'd like to do is replace MethodOne(), MethodTwo(), ..., Method Nineteen()
// with something like:
RunMethod<void>(MethodOneWork, new object[] {"x"});
ret = RunMethod<int>(MethodTwoWork, new object []{1});
//.
//.
//.
RunMethod<void>(MethodNineteenWork, null);
}
private static void MethodOne(string st)
{
try
{
// the try clause is the only difference between the methods
MethodOneWork(st);
}
catch (MyExceptionA)
{
HandleExceptionA();
return;
}
catch(MyExceptionB)
{
HandleExceptionB();
}
catch(Exception)
{
HandleGenericException();
}
}
private static int MethodTwo(int v)
{
try
{
return MethodTwoWork(v);
}
catch (MyExceptionA)
{
HandleExceptionA();
return -1;
}
catch (MyExceptionB)
{
HandleExceptionB();
return -2;
}
catch(Exception)
{
HandleGenericException();
return 0;
}
}
private static void MethodNineteen()
{
try
{
MethodNineteenWork();
}
catch (MyExceptionA)
{
HandleExceptionA();
return;
}
catch (MyExceptionB)
{
HandleExceptionB();
}
catch(Exception)
{
HandleGenericException();
}
}
/// <summary>
/// Run generic method with generic signature
/// </summary>
private static <T> RunMethod(Delegate MethodxWork, object[] myParams)
{
try
{
new <T>() retVal = MethodxWork(myParams);
return retVal;
}
catch (MyExceptionA)
{
HandleExceptionA();
return new <T>();
}
catch (MyExceptionB)
{
HandleExceptionB();
return new <T>();
}
catch(Exception)
{
HandleGenericException();
return new <T>();
}
}
private static void HandleExceptionB()
{
//handle it
}
private static void HandleExceptionA()
{
//handle it
}
private static void HandleGenericException()
{
//handle it
}
}
internal class MyExceptionB : Exception
{
}
internal class MyExceptionA : Exception
{
}

Sure, just create a few methods whose job it is to handle the exceptions, one for returning results and the other for void, and provide something that does your work.
T Handle<T>(Func<T> call)
{
try
{
return call();
}
catch(YourException ex)
{
return default;
}
}
void Handle(Action call)
{
try
{
call();
}
catch(YourException ex)
{
}
}
After that, you can call your other methods with varying signatures inside there.
var result = Handle(() => SomeCallWithVaryingSignature(...));
Handle(() => SomeOtherCall(...));

Related

Refactoring a WCF Trusted Facade

I'm attempting to refactor a "trusted facade" which currently wraps over 50 service calls to the backend. All calls have different signatures, but everything else is being repeated. The issue with the existing calls was that there was no attempt made to manage the connections, resulting in ephemeral ports remaining in the "BOUND" state.
ORIGINAL CODE:
public class ReportWeb : IReportWeb
{
ReportService.ReportClient client = new ReportClient();
...
public string[] GetAccounts() => client.GetAccounts();
}
NEW CODE:
private ChannelFactory<IReportService> _factory = null;
private IReportService _proxy = null;
private void OpenProxy()
{
_factory = new ChannelFactory<IReportService>("NetTcpBinding_IReportService");
_proxy = _factory.CreateChannel();
}
private void CloseProxy()
{
((IClientChannel)_proxy).Close();
_factory.Close();
}
One of 50+ similar methods:
public string[] GetAccounts() // Different - name, params, and return type
{
string[] accounts = null; // Different
try
{
OpenProxy();
accounts = _proxy.GetAccounts(); // Different
CloseProxy();
}
catch (Exception exception)
{
bool faulted = _factory.State == CommunicationState.Faulted;
_factory.Abort();
if (faulted)
{
throw new ApplicationException(exception.Message);
}
else
{
throw;
}
}
return accounts;
}
Another similar method:
//Another method
public ContractsInfo[] GetContracts(int contractId) // Different -
// name, params, and return type
{
ContractsInfo[] contracts = null; // Different
try
{
OpenProxy();
contracts = _proxy.GetContracts(contractId); // Different
CloseProxy();
}
catch (Exception exception)
{
bool faulted = _factory.State == CommunicationState.Faulted;
_factory.Abort();
if (faulted)
{
throw new ApplicationException(exception.Message);
}
else
{
throw;
}
}
return contracts;
}
Calling code from Web Forms project:
public string[] GetAccounts()
{
ReportClient client = NewReportClient();
string[] results = null;
try
{
results = client.GetAccounts();
client.Close();
}
catch (Exception ex)
{
client.Abort();
throw ex;
}
return results;
}
There are over fifty other methods like GetData() with different signatures. They will all be identical except for the service call in each, which will vary in params and return type. I need a more abstract, or generic, way of coding this and thus adhere to the DRY principle. Would Func<T, TResult> Delegate be appropriate here? Either way, can someone suggest a best approach here with some stub code to illustrate?
I suppose that this is the case where Generic method with can be applied. It is
possible to read about Generics here
Let me show a code example:
public class Foo
{
public T GetDate<T, UArg>(UArg arg) where T : new()
{
return new T();
}
}

Design pattern for handling if else with different implementations

I have the following two types of processors
public interface IDefaultProcessor1
{
void Process(IProcess p);
}
public interface IDefaultProcessor2
{
T Process<T>(IProcess p);
}
public class DefaultProcessor : IDefaultProcessor1
{
public void Process(IProcess p)
{
try
{
foreach ...
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
}
public class AnotherProcessor : IDefaultProcessor2
{
public T Process<T>(IProcess p)
{
try
{
foreach ...
return p.Result()...
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
}
Most of the implementation code is exactly the same (error checking etc) except one returns a value. Is there a pattern to clean this up?
Yes, there is.
Define both methods on the same interface:
public interface IDefaultProcessor
{
void Process(IProcess p);
TResult Process<TResult>(IProcess p);
}
And then:
public class DefaultProcessor : IDefaultProcessor
{
public void Process(IProcess p)
{
DoProcess(p);
}
public TResult Process<TResult>(IProcess p)
{
object result = DoProcess(p);
return (TResult)result;
}
private object DoProcess(IProcess p)
{
try
{
foreach ...
return p.Result();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
}
There are many ways you can do this. One thing you have to keep in mind is that there is no way you can have a method with a optional return. That been said, you can try one of the aproaches below:
Implement Template Pattern and return null to your process that don't return anything:
public abstract class AbstractProcess<T>
{
public abstract T DoProcess();
public T Process()
{
//do your common tasks
return DoProcess();
}
}
public class Process1 : AbstractProcess<Process1>
{
public override Process1 DoProcess()
{
return new Process1();
}
}
public class Process2 : AbstractProcess<Process2>
{
public override Process2 DoProcess()
{
return null;
}
}
Create an Interface with both methods, and then choose what is the best method to call (as pointed by Matias CĂ­cero)
public interface IProcessor
{
T Process<T>();
void Process();
}
public class Processor : IProcessor
{
public void Process()
{
DoWork();
}
public T Process<T>()
{
return (T)DoWork();
}
public object DoWork()
{
// do your common tasks
}
}
Create an Interface with a single method and decide if you will return something (or null) based on the type:
public interface IProcessor
{
T Process<T>() where T : class;
}
public class Processor : IProcessor
{
public T Process<T>() where T : class
{
var result = (T)DoWork();
if (typeof(T) == typeof(Process2))
return result;
return null;
}
public object DoWork()
{
// do your common tasks
}
}

Passing functions with varying numbers and types of parameters

I have a lot of functions that look like this:
public void DoParticularThing(RecurringTaskRunResult result) {
try {
// Do a bunch of stuff
}
catch (Exception e) {
result.Succeeded = false;
result.Results += e.ToString();
db.SaveChanges();
}
}
So I decided to extract this out in the name of DRY code:
public void RunThing(Action<RecurringTaskRunResult> action, RecurringTaskRunResult result) {
try {
action(result);
}
catch (Exception e) {
result.Succeeded = false;
result.Results += e.ToString();
db.SaveChanges();
}
}
This way I can call DoParticularThing like this:
RunThing(DoParticularThing, result);
But some of my functions also accept another parameter:
public void DoOtherParticularThing(RecurringTaskRunResult result, List<string> strings) {
try {
// Do a bunch of stuff
}
catch (Exception e) {
result.Succeeded = false;
result.Results += e.ToString();
db.SaveChanges();
}
}
How can I modify RunThing to optionally accept another parameter?
Perhaps this :
public void RunThing(Action action, RecurringTaskRunResult result) {
try {
action();
}
catch (Exception e) {
result.Succeeded = false;
result.Results += e.ToString();
db.SaveChanges();
}
}
RunThing(() => DoParticularThing(result), result);
RunThing(() => DoSomethingElse(result, list), result);
You can use params accept any parameters in your function.
public void RunThing(Action<RecurringTaskRunResult> action, RecurringTaskRunResult result, params object[] list) {
try {
action(result);
foreach(var item in list)
{
// Do action with your additional parameter
}
}
catch (Exception e) {
result.Succeeded = false;
result.Results += e.ToString();
db.SaveChanges();
}
}
It looks like in all cases you want RunThing to have access to the RecurringTaskRunResult so that you can set some fields on it, but that you don't need access to any of the other parameters. You could try something like this:
void Action1(RecurringTaskRunResult result) { }
void Action2(RecurringTaskRunResult result, object foo) { }
RecurringTaskRunResult result = ...;
object foo = ...;
RunThing(Action1, result);
RunThing(res => Action2(res, foo), result);

Create custom validation attributes c# server side

I'm trying to create Validation Attribute to enforce licensing in my solution.
The way I've tried to do it is using by LicenseValidationAttribute that inherits from ValidationAttribute.
The main goal is when CreateProject() method is called, if the customer already reached the limit of projects he is entitled for, that will lead to exception throwing. else, that will be OK flow.
I've write a small program but unfortunately it doesn't work, means it doesn't throws exception.
The program:
[AttributeUsage(AttributeTargets.Method)]
public class MyValidationAttribute : ValidationAttribute
{
public MyValidationAttribute()
{
}
public override bool IsValid(object value)
{
int id = (int)value;
if (id > 0)
return true;
throw new Exception("Error");
}
}
public class Service
{
[MyValidation]
public bool GetService(int id)
{
if (id > 100)
{
return true;
}
return false;
}
}
static void Main(string[] args)
{
try
{
Service service = new Service();
service.GetService(-8);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); ;
}
}
Thanks!
After adding System.reflection's GetCustomAttributes method call it works:
static void Main(string[] args)
{
try
{
Service service = new Service();
service.GetService(-8);
service.GetType().GetCustomAttributes(false);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); ;
}
}

A Try-Catch Block Macro equivalent in C#?

Here is a sample C++ macro that I use to make my code more readable and reduce the Try-Catch Clutter:
#define STDTRYCATCH(expr) \
try { \
return (expr); \
} \
catch (const std::exception& ex) { \
handleException(ex); \
} \
catch (...) { \
handleException(); \
}
Which can be used as:
int myClass::Xyz()
{
STDTRYCATCH(myObj.ReadFromDB());
}
Please note that I'm looking for STDTRYCATCH that handles any code stub we enclose with it.Is there an equivalent in C# ?
You can write helper:
public static class ExcetpionHandler
{
public static void StdTryCatch(this object instance, Action act)
{
try
{
act();
}
catch (Exception ex)
{
var method = instance.GetType().GetMethod("StdException");
if (method != null)
{
method.Invoke(instance, new object[] {ex});
}
else
{
throw;
}
}
}
}
Usage:
public class MyClass
{
public void StdException(Exception ex)
{
Console.WriteLine("Thrown");
}
public void Do()
{
this.StdTryCatch(() =>
{
throw new Exception();
});
}
}
and:
class Program
{
static void Main(string[] args)
{
var instance = new MyClass();
instance.Do();
}
}
But it is not recommeded - due to performance reasons etc - like mentioned in comments.
EDIT:
Like cdhowie mentioned, you can also prepare inteface:
public interface IExceptionHandler
{
void StdException(Exception ex);
}
Then:
public static class ExcetpionHandler
{
public static void StdTryCatch(this IExceptionHandler instance, Action act)
{
try
{
act();
}
catch (Exception ex)
{
instance.StdException(ex);
}
}
}
Your class then need to impelement that interface.

Categories