views:

55

answers:

3

All i have something i have been trying to do for a while and have yet to find a good strategy to do it, i am not sure C# can even support what i am trying to do.

Example imagine a template like this, repeated in manager code overarching cocept function Returns a result consisting of a success flag and error list.

       public Result<Boolean> RemoveLocation(LocationKey key)
        {
           List<Error> errorList = new List<Error>();
           Boolean result = null;
           try{
                result  = locationDAO.RemoveLocation(key);
           }catch(UpdateException ue){
               //Error happened less pass this back to the user!
               errorList = ue.ErrorList;
           }

           return new Result<Boolean>(result, errorList);
        }

Looking to turn it into a template like the below where Do Something is some call (preferably not static) that returns a Boolean. I know i could do this in a stack sense, but i am really looking for a way to do it via object reference.

        public Result<Boolean> RemoveLocation(LocationKey key)
        {
             var magic =  locationDAO.RemoveLocation(key);

             return ProtectedDAOCall(magic);
        }
        public Result<Boolean> CreateLocation(LocationKey key)
        {
             var magic =  locationDAO.CreateLocation(key);

             return ProtectedDAOCall(magic);
        }


        public Result<Boolean> ProtectedDAOCall(Func<..., bool> doSomething)
        {
           List<Error> errorList = new List<Error>();
           Boolean result = null;
           try{
                result  = doSomething();
           }catch(UpdateException ue){
               //Error happened less pass this back to the user!
               errorList = ue.ErrorList;
           }

           return new Result<Boolean>(result, errorList);
        }

If there is any more information you may need let me know.

I am interested to see what someone else can come up with.


Marc solution applied to the code above

    public Result<Boolean> CreateLocation(LocationKey key)
    {
        LocationDAO locationDAO = new LocationDAO();
        return WrapMethod(() => locationDAO.CreateLocation(key));
    }


    public Result<Boolean> RemoveLocation(LocationKey key)
    {
        LocationDAO locationDAO = new LocationDAO();
        return WrapMethod(() =>  locationDAO.RemoveLocation(key));
    }


    static Result<T> WrapMethod<T>(Func<Result<T>> func)
    {
        try
        {
            return func();
        }
        catch (UpdateException ue)
        {
            return new Result<T>(default(T), ue.Errors);
        }
    }
A: 

We have the following in our project, it looks very similar

        public TResult DoCall<TResult,TProvider>(Func<TProvider, TResult> action) where TProvider : class, IProvider
        {
            TResult ret = default(TResult);
            try
            {
                var prov = (TProvider) ModelManagerProvider.GetProviderByType(typeof(TProvider));
                ret = action(prov);
            }
            catch (Exception ex)
            {
                ThrowErrorTool.ThrowError(ex);
            }
            return ret;
        }

and here is how we call it

        public bool UpdateAdverseEventSection(AdverseEventsDTO aeDTO)
        {
            return DoCall((AdverseEventsProvider r) => r.UpdateAdverseEventSection(aeDTO));
        } 
vittore
Sorry i think this is a little too much, but it is a good example, if you could make it more generic it would help... the thing i dont need is the concept (in ur code) of a TProvider. I just have some action i want to execute, no need to pass it.yours is much more generic then i need.
Nix
+1  A: 

Something like:

public Result<Boolean> RemoveLocation(LocationKey key)
{
    return WrapMethod(() => locationDAO.RemoveLocation(key));
}
static Result<T> WrapMethod<T>(Func<T> func) {
    try
    {
        return new Result<T>(func());
    }
    catch (SomeExceptionBase ex)
    {
        return new Result<T>(ex.ErrorList);
    }
    catch (Exception ex)
    {
        return new Result<T>((List<Error>)null);
    }
}

and (minimum shown)

class Result<T>
{
    private Result(bool isError, T value, List<Error> erors) { }
    public Result(T value) : this(false, value, null){ }
    public Result(List<Error> errors) : this(true, default(T), errors) { }
}
class SomeExceptionBase : Exception
{
    public List<Error> ErrorList { get; private set; }
}

(although if I had to do this I'd probably do something more interesting with exceptions that don't happen to be SomeExceptionBase)

Marc Gravell
Still testing it out, but with some minor teaks WrapMethod signature should be Result<T> (you might want to edit) WrapMethod<T>(Func<Result<T>> func) {Thanks. Once i validate everything is functional i will mark.
Nix
@Nix - I'm not convinced, you know. `Func<bool>` works fine...? That is kinda the point, isn't it? To turn "something that returns `bool` " (i.e. `Func<bool>` into `Result<bool>`?
Marc Gravell
i think the misunderstanding is that the dao returns a result<bool>
Nix
i posted solution above, hopefully it clears up what i was trying to do(frustratingly simple).
Nix
A: 
static Result<T> WrapMethod<T>(Func<LocationDao, Result<T>> func) 
{ 
    try 
    { 
        var l = new LocationDao();
        return func(l); 
    } 
    catch (UpdateException ue) 
    { 
        return new Result<T>(default(T), ue.Errors); 
    } 
} 
public Result<Boolean> RemoveLocation(LocationKey key)     
{                  
    return WrapMethod((l) =>  l.RemoveLocation(key));     
} 
vittore
problem is it wont always be locationdao, it could be another type.....
Nix
that's why we have TProvider in our example
vittore