gsharp
gsharp

Reputation: 27927

Generic problem with List

I'm trying to make a Parallel Helper class (ParallelRunner) that can be used like in the RequestService class:

public class ParallelFunction
{
    public ParallelFunction(Func<object> function)
    {
        Function = function;
    }

    public T GetResult<T>() where T : class
    {
        return (T) Data;
    }

    public Func<object> Function { get; private set; }
    public object Data { private get; set; }
}

public static class ParallelRunner
{
    public static void Run( IEnumerable<ParallelFunction> parallelFunctions)
    {
        Parallel.ForEach(parallelFunctions, f =>{f.Data = f.Function();});
    }
}


public class RequestService
{
    public void DoParallel()
    {
        var da = new RequestDataAccess();
        var pf1 = new ParallelFunction(da.GetRequests);
        var pf2 = new ParallelFunction(da.GetRequestAnswers);

        ParallelRunner.Run(new List<ParallelFunction> { pf1, pf2 });

        var requests = pf1.GetResult<List<Request>>();
        var answers = pf2.GetResult<List<RequestAnswer>>();
    }
}

what I really would love to have was a generic ParallelFunction Class like that:

public class ParallelFunction<T>  where T : class
{
    public ParallelFunction(Func<T> function)
    {
        Function = function;
    }

    public Func<T> Function { get; private set; }
    public T Data { get; set; }
}

And instead of getting the Data From the GetResult<T> that does a cast of the desired type, getting the Data from the T Data property.

The problem is here ParallelRunner.Run(new List<ParallelFunction> { pf1, pf2 }); if ParallelFunction is with the generic i'm of course not able to add tow different types into the list.

Maybe someone have a good idea how to solve that?

Upvotes: 2

Views: 168

Answers (2)

flq
flq

Reputation: 22829

IN such situations where generic types are exposed to non-generic infrastructure, I introduce an interface that is non-generic:

public class ParallelFunction<T> : IParallelFunction
{
    private readonly Func<T> function;

    public ParallelFunction(Func<T> function)
    {
        this.function = function;
    }

    public void CacheResult()
    {
        Data = function();
    }

    public T Data { get; private set; }
}

You see, I changed the design a bit to expose less of the stuff that the class does. The interface can expose non-generic bits "CacheResult". Your Helper can now work off the interface by invoking the Cacheresult method. Outside the helper you can still have your generic implementations.

public static class ParallelRunner
{
    public static void Run(IEnumerable<IParallelFunction> parallelFunctions)
    {
        Parallel.ForEach(parallelFunctions, f => f.CacheResult());
    }
}

Upvotes: 1

Dario
Dario

Reputation: 49208

Use a variant generic interface IParallelFunc<out T> that ParallelFunc<T> implements. Then, a IParallelFunc<int> and a IParallelFunc<string> could both be generalized to a IParallelFunc<object> and be handled by your method.

Upvotes: 1

Related Questions