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
}
}
Related
I have a base class that defines an abstract method that returns a Task.
public abstract class BaseClass
{
public abstract Task DoSomething();
}
I can make a class that implements the abstract method in these two different ways.
public class Example1 : BaseClass
{
public override Task DoSomething()
{
return Task.CompletedTask;
}
}
or like this
public class Example2 : BaseClass
{
public override async Task DoSomething()
{
}
}
Notice that the first returns a completed task, the second includes the async keyword and doesn't have a return statement. Is there any difference between the two?
There is significant difference in the code that gets generated. By merely adding the async keyword the method gets compiled very differently.
Here's effectively what the compiler produces:
public class Example2 : BaseClass
{
private struct DoSomethingStateMachine : IAsyncStateMachine
{
public int _state;
public AsyncTaskMethodBuilder _builder;
private void MoveNext()
{
try
{
}
catch (Exception exception)
{
_state = -2;
_builder.SetException(exception);
return;
}
_state = -2;
_builder.SetResult();
}
void IAsyncStateMachine.MoveNext()
{
this.MoveNext();
}
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
_builder.SetStateMachine(stateMachine);
}
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
this.SetStateMachine(stateMachine);
}
}
public override Task DoSomething()
{
DoSomethingStateMachine stateMachine = default(DoSomethingStateMachine);
stateMachine._builder = AsyncTaskMethodBuilder.Create();
stateMachine._state = -1;
AsyncTaskMethodBuilder _builder = stateMachine._builder;
_builder.Start(ref stateMachine);
return stateMachine._builder.Task;
}
}
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(...));
I am trying to build a generic query handler using the MediatR (v8) library. Lets jump to the code:
First of all I have an abstract query class like this:
public abstract class Query<TQueryResult> : IRequest<TQueryResult>
{
public Guid Id { get; } = Guid.NewGuid();
public DateTime Timestamp { get; }
protected Query()
{
Timestamp = DateTime.Now;
}
}
From the corresponding query handler I would like to return a Result wrapper object, which looks as the following:
public class Result<T>
{
public T Payload { get; }
public string FailureReason { get; }
public bool IsSuccess => FailureReason == null;
public Result(T payload)
{
Payload = payload;
}
public Result(string failureReason)
{
FailureReason = failureReason;
}
public static Result<T> Success(T payload)
=> new Result<T>(payload);
public static Result<T> Failure(string reason)
=> new Result<T>(reason);
public static implicit operator bool(Result<T> result) => result.IsSuccess;
}
And last but not least, lets see the query handler:
public abstract class AbstractQueryHandler<TQuery, TQueryResult, TResultValue> : IRequestHandler<TQuery, TQueryResult>
where TQuery : Query<TQueryResult>
where TQueryResult : class
{
public Task<TQueryResult> Handle(TQuery request, CancellationToken cancellationToken)
{
try
{
return HandleQuery(request);
}
catch (Exception e)
{
return Task.FromResult(Result<TResultValue>.Failure(GetFailureMessage(e)) as TQueryResult);
}
}
public abstract Task<TQueryResult> HandleQuery(TQuery request);
private static string GetFailureMessage(Exception e)
{
return "There was an error while executing query: \r\n" + e.Message;
}
}
To be honest I am not pleased with this solution due to the three type parameters I have in the query handler. Let's see some corresponding tests to reveal my concerns regarding. First the test-helper objects:
public class ExampleDto
{
public string Name { get; set; }
}
public class BasicQuery : Query<Result<ExampleDto>>
{
}
public class BasicQueryHandler : AbstractQueryHandler<BasicQuery, Result<ExampleDto>, ExampleDto>
{
public override Task<Result<ExampleDto>> HandleQuery(BasicQuery request)
{
return Task.FromResult(Result<ExampleDto>.Success(new ExampleDto() { Name = "Result Name" }));
}
}
And then the test:
[Fact]
public async Task GivenBasicQuery_whenHandle_thenSuccessResultWithPayload()
{
var handler = new BasicQueryHandler();
var result = await handler.Handle(new BasicQuery(), CancellationToken.None);
Check.That(result.IsSuccess).IsTrue();
Check.That(result.Payload.Name).IsEqualToValue("Result Name");
}
As you can see in the BasicQueryHandler there is some kind of duplication when declaring the three types, namely <BasicQuery, Result<ExampleDto>, ExampleDto>. It seems really fishy to me. I also tried many other possibilities, checking articles and SO questions/answers on the internet but could not come up with a cleaner solution with. What am I doing wrong? Is it possible to reduce the number of type parameters (of query handler) to 2? Thanks in advance for you help!
Basically, I moved the Result<> from the type parameter in the class declaration to the method declaration. I also removed the interfaces for clarity (you didn't share the definitions anyway).
public abstract class AbstractQueryHandler<TQuery, TQueryResult>
where TQuery : Query<TQueryResult>
where TQueryResult : class, new()
{
public Task<Result<TQueryResult>> Handle(TQuery request, CancellationToken cancellationToken)
{
try
{
return HandleQuery(request);
}
catch (Exception e)
{
return Task.FromResult(Result<TQueryResult>.Failure(new TQueryResult(), GetFailureMessage(e)));
}
}
public abstract Task<Result<TQueryResult>> HandleQuery(TQuery request);
private static string GetFailureMessage(Exception e)
{
return "There was an error while executing query: \r\n" + e.Message;
}
}
public class BasicQueryHandler : AbstractQueryHandler<BasicQuery, ExampleDto>
{
public override Task<Result<ExampleDto>> HandleQuery(BasicQuery request)
{
return Task.FromResult(Result<ExampleDto>.Success(new ExampleDto() { Name = "Result Name" }));
}
}
Note that since you need to new up a TQueryResult in the exception path, the new() keyword had to be added to the generic constraint.
I have a generic delegate like this:
public delegate T SomeHandler<T>(T input);
I have a generic class that take the delegate as a parameter to its constructor like this:
public class SomeClass<T>
{
private SomeHandler<T> m_handler;
public SomeClass(SomeHandler<T> handler)
{
m_handler = handler;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
// some stuff
}
}
Most of the time I would instantiate the class with a default handler unless some special case is needed. So I have some default handlers for the types I use:
public static class DefaultHandlers
{
public static string DefaultStringHandler(string input)
{
return input;
}
}
In some cases, the type is instantiated with a special handler that is specific to its implementation:
public class Example
{
private SomeClass<string> m_typicalCase;
private SomeClass<string> m_specialCase;
public Example()
{
m_typicalCase = new SomeClass<string>(DefaultHandlers.DefaultStringHandler);
m_specialCase = new SomeClass<string>(SpecialHandler);
}
private string SpecialHandler(string input)
{
string result;
// Do something special
return result;
}
}
I want to create a default constructor for SomeClass that always instantiates the class with the same default handler for that type, but since the type is not know at compile time, I can't return the delegate that is the right type.
public class SomeClass<T>
{
...
public SomeClass()
{
m_handler = DefaultHandlers.GetDefaultHandler<T>();
}
...
}
Like this
public static class DefaultHandlers
{
public static SomeHandler<T> GetDefaultHandler<T>()
{
if (typeof(T) == typeof(string))
{
return DefaultStringHandler;
}
}
}
This does not work becuase DefaultStringHandler returns a string and the method expects T.
The only way that I have found to do this is the make a type-specific subclass of SomeClass that overloads the default constructor:
public class SomeStringClass : SomeClass<string>
{
public SomeStringClass()
: base(DefaultHandlers.DefaultStringHandler)
{
}
public SomeStringClass(SomeHandler<string> handler)
: base(handler)
{
}
}
It would be fun if generic types could have type-specific overloaded constructors that are used when instantiating the class of a specific type:
public class Foo<T>
{
public Foo<string>(string input)
{
}
public Foo<int>(int input)
{
}
public Foo(T input)
{
}
}
There must be a more elegant way to do with with a design pattern, Strategy maybe?
You could utilize dynamic to get something like SomeClass<string>():
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Zoltan
{
public class SomeClass<T>
{
private static readonly Func<T,T> FALL_BACK_HANDLER = a => a; //or what have you
private readonly Func<T,T> m_handler;
public SomeClass(Func<T,T> handler)
{
m_handler = handler;
}
public SomeClass()
{
m_handler = DefaultHandler.For<T>() ?? FALL_BACK_HANDLER;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
Console.WriteLine(result);
}
}
public static class DefaultHandler
{
public static Func<T,T> For<T>()
{
return TypeAware<T>.Default;
}
private static class TypeAware<T>
{
private static readonly Func<T,T> DEFAULT;
static TypeAware()
{
var type = typeof(T);
if (type == typeof(string))
{
DEFAULT = a => DefaultHandler.StringHandler((dynamic) a);
}
else if (type == typeof(int))
{
DEFAULT = a => DefaultHandler.IntHandler((dynamic) a);
}
else
{
DEFAULT = null;
}
}
public static Func<T,T> Default { get { return DEFAULT; } }
}
public static string StringHandler(string a)
{
return a + " The default handler does some stuff!";
}
public static int IntHandler(int a)
{
return a + 2;
}
}
}
You would then consume SomeClass as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Zoltan
{
public class Program
{
public static void Main(string[] args)
{
var someStringObj = new SomeClass<string>();
someStringObj.DoSomeStuff("Hello World.");//prints "Hello World. The default handler does some stuff!"
var someIntObj = new SomeClass<int>();
someIntObj.DoSomeStuff(1);//prints 3
var someCustomDoubleObj = new SomeClass<double>(d => d - 2);
someCustomDoubleObj.DoSomeStuff(3);//prints 1
Console.Read();
}
}
}
Building on Jon Skeet and Alexei Levenkovs comments. From what I understand, something like this might be what you're after?
public delegate T SomeHandler<T>(T input);
public class SomeClass<T>
{
private SomeHandler<T> m_handler;
public SomeClass()
{
m_handler = (T input) => input;
}
public SomeClass(SomeHandler<T> handler)
{
m_handler = handler;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
// some stuff
}
}
Another way would be to move the string-specific behaviour into a separate class and simply make an instance of that class if you want specific behaviour tied to a specific type
public delegate T SomeHandler<T>(T input);
public class SomeClass<T>
{
protected SomeHandler<T> m_handler;
protected SomeClass()
{
}
public SomeClass(SomeHandler<T> handler)
{
m_handler = handler;
}
public void DoSomeStuff(T input)
{
T result = m_handler(input);
// some stuff
}
}
public class SomeStringClass : SomeClass<string>
{
public SomeStringClass()
{
m_handler = DefaultStringHandler;
}
private string DefaultStringHandler(string input)
{
// Do default string stuff here...
return input;
}
public SomeStringClass(SomeHandler<string> handler):base(handler)
{
}
}
I have the following class hierarchy:
EstadoBaseMO (parent)
EstadoSAMO(EstadoBaseMO child)
EstadoGesDocMO(EstadoBaseMO child)
SolicitudBasePresenter(parent)
SolicitudGesDocPresenter(SolicitudBasePresenter child)
SolicitudSAPresenter(SolicitudBasePresenter child)
EstadoBaseBO(parent)
EstadoGesDocBO(EstadoBaseBO child)
EstadoSABO(EstadoBaseBO child)
I need to implement a method called SaveNewDetailStates, with the following implementation in SolicitudBasePresente is
public bool SaveNewDetailStates(List<EstadoBaseMO> estados)
{
bool result = true;
if (estados.Any())
{
try
{
EstadoGesDocBO bo = new EstadoGesDocBO();
foreach (var estado in estados)
{
var savedState = bo.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
SolicitudGesDocPresenter.SaveNewDetailStates implementation
public bool SaveNewDetailStates(List<EstadoGesDocMO> estados)
{
bool result = true;
if (estados.Any())
{
try
{
EstadoGesDocBO bo = new EstadoGesDocBO();
foreach (var estado in estados)
{
var savedState = bo.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
SolicitudSAPresenter.SaveNewDetailStates implementation
public bool SaveNewDetailStates(List<EstadoSAMO> estados)
{
bool result = true;
if (estados.Any())
{
try
{
EstadoSABO bo = new EstadoSABO();
foreach (var estado in estados)
{
var savedState = bo.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
As you can see, the code is exactly the same with two differences, in SolicitudSAPresenter I'm using EstadoSAMO and EstadoSABO classes, similar in SolicitudGesDocPresenter.
Things to know:
I don't really need an implementation of SolicitudBasePresenter.SaveNewDetailStates
I tried to convert the parent method(SolicitudBasePresenter.SaveNewDetailStates) to an abstract method, but then, the SAPresenter and GesDocPresenter can't use override because they need to implement the same signature (and it's not the same..), besides, soon after I realized I need a concrete implementation of SolicitudBasePresenter, so it shouldn't be an abstract class (similar happens with a virtual method)
Maybe the use of generics can solve that problem, but I'm still not used to them. I tried with something like SaveNewDetailStates<T,K>(List<T> estados), but then I'm lost and I don't know what else can I do.
What is the best approach for writing this code?
The only solution I have is to delete the SaveNewDetailStates from parent presenter, and write the concrete implementation in children and then everything is fine but...I don't think that's even a solution for a good developer..
You need to use Generics. Define the class EstadoBaseMO<T> and then use the type T in your save method.
public bool SaveNewDetailStates(List<T> estados)
Your child classes can then (for example) extend EstadoBaseMO<SolicitudBasePresenter>.
There are lots of generics tutorials online, have a look at some of them.
https://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx
you can use Generics but you still need to use Interfaces to implement what you need, but you can do it only with Interfeces similar to this, I made separate IEstadoState and IEstadoMO to make it more clear if you don't need additional fields in your logic you can make one interface instead of these two
public interface IEstadoState
{
int Id { get; set; }
}
public interface IEstadoMO
{
int Id { get; set; }
}
public interface IEstadoBO
{
IEstadoState Insert(IEstadoMO estadoMO);
}
public class SolicitudBasePresenter
{
public virtual bool SaveNewDetailStates(List<IEstadoMO> estados, IEstadoBO estadoBO)
{
bool result = true;
if (estados.Any())
{
try
{
foreach (var estado in estados)
{
var savedState = estadoBO.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
}
public class SolicitudGesDocPresenter : SolicitudBasePresenter { }
public class SolicitudSAPresenter : SolicitudBasePresenter { }
if you prefer to use Generic or don't want to pass second parameter to method here is how it will look
public class SolicitudBasePresenter<T1, T2> where T1 : IEstadoMO where T2 : IEstadoBO, new()
{
public bool SaveNewDetailStates(List<T1> estados)
{
bool result = true;
if (estados.Any())
{
try
{
foreach (var estado in estados)
{
var estadoBO = new T2();
var savedState = estadoBO.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
}
public class EstadoState : IEstadoState
{
public int Id {get; set;}
}
public class EstadoBaseMO : IEstadoMO
{
public int Id { get; set; }
}
public class EstadoBaseBO : IEstadoBO
{
public IEstadoState Insert(IEstadoMO estado) { return new EstadoState(); }
}
public class EstadoSAMO : EstadoBaseMO { }
public class EstadoGesDocMO : EstadoBaseMO { }
public class EstadoGesDocBO : EstadoBaseBO { }
public class EstadoSABO : EstadoBaseBO { }
public class SolicitudGesDocPresenter : SolicitudBasePresenter<EstadoGesDocMO, EstadoGesDocBO> { }
public class SolicitudSAPresenter : SolicitudBasePresenter<EstadoSAMO, EstadoSABO> { }
your method call will be
var docPresenter = new SolicitudGesDocPresenter();
docPresenter.SaveNewDetailStates(new List<EstadoGesDocMO>());
also you can declare children like this
public class SolicitudGesDocPresenter<T1, T2> : SolicitudBasePresenter<T1, T2> where T1 : IEstadoMO where T2 : IEstadoBO, new() { }
public class SolicitudSAPresenter<T1, T2> : SolicitudBasePresenter<T1, T2> where T1 : IEstadoMO where T2 : IEstadoBO, new() { }
you'll call it in this way
var docPresenter = new SolicitudGesDocPresenter<EstadoGesDocMO, EstadoGesDocBO>();
docPresenter.SaveNewDetailStates(new List<EstadoGesDocMO>());