Reputation: 8450
In order to reduce the amount of code our team put in a StartProcess method to call the WCF implementation for all calls from a single method. It all works great, but since the actual call from the generic method uses a System.Action to invoke, it can never return a value and since one of the calls I am making I would like to make a request/reply, I can't get that return value.
Here is the Generic method to handle the WCF requests:
public static ProcessResultDC StartProcess<T>(T setupData, string processName, Action<T> action, string exteriorAccountNumber, string companyCode) where T : IAmValidatable, IHaveAProcessGuid {
var result = new ProcessResultDC { Status = ProcessStatusEnum.Accepted };
// Do some authentication stuff here
try {
action(setupData); // <-- This returns void, but I would like to return a string to the client
} catch (Exception exc) {
result.Status = ProcessStatusEnum.Error;
result.Messages.Add(exc.Message);
}
return result;
}
And here is the client call:
var createOnDemandDataDc = new CreateOnDemandDataDc { RawData = punchRawData };
var result = TimeForceProcessHelper.StartProcess(createOnDemandDataDc, "Create On Demand Data", x => new CreateOnDemandDataProxy().CreateOnDemandData(createOnDemandDataDc), "NA", companyCode);
The result variable has no way of knowing about the string from the action call, even though my createOnDemandDataDc implementation returns a string.
Is there a better way to do this? Or can I simply do something other than an Action() call in order to get the return string?
Upvotes: 0
Views: 356
Reputation: 24383
This is how I do AOP too. You need two methods for each aspect - one for an Action
and one for a Func
If you write the one for Func
first:
public static ProcessResultDC StartProcess<T, TResult>(
T setupData,
string processName,
Func<T, TResult> fn,
string exteriorAccountNumber,
string companyCode
)
where T : IAmValidatable, IHaveAProcessGuid
{
var result = new ProcessResultDC { Status = ProcessStatusEnum.Accepted };
// Do some authentication stuff here
try
{
result.Result = fn(setupData);
}
catch (Exception exc)
{
result.Status = ProcessStatusEnum.Error;
result.Messages.Add(exc.Message);
}
return result;
}
Then you can write the one for Action
to use the Func
implementation:
public static ProcessResultDC StartProcess<T>(
T setupData,
string processName,
Action<T> fn,
string exteriorAccountNumber,
string companyCode
)
where T : IAmValidatable, IHaveAProcessGuid
{
return StartProcess(
setupData,
processName,
t => { fn( t ); return 0; },
exteriorAccountNumber,
companyCode
);
}
Upvotes: 1
Reputation: 36082
Instead of using Action<T>
for the callback param, you could use Func<T, TResult>
to allow the callback to return a value to the StartProcess
caller. However, this will require that all your callbacks would need to be changed to functions that return a value. Probably not a happy thought if you only have one callback that needs to return a reply.
Another somewhat dirty approach might be to write your response to the currently active OperationContext directly in your CreateOnDemandDataDc callback function. Look at OperationContext.Current.RequestContext.Reply
and related properties/methods.
Upvotes: 2