2010-10-04 4 views
2

Je suis en train de faire une classe d'aide parallèle (ParallelRunner) qui peut être utilisé comme dans la RequestService classe:problème générique avec Liste

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>>(); 
    } 
} 

ce que je vraiment avoir était une classe générique ParallelFunction comme que:

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; } 
} 

Et au lieu d'obtenir les données de la GetResult<T> qui fait une distribution du type souhaité, obtenir les données de la propriété T Data.

Le problème est ici ParallelRunner.Run(new List<ParallelFunction> { pf1, pf2 }); si ParallelFunction est avec le générique je ne suis bien sûr pas en mesure d'ajouter deux types différents dans la liste.

Peut-être que quelqu'un a une bonne idée de comment résoudre ce problème?

+0

Je ne pense pas que ce que vous demandez est directement possible, vous pourriez avoir une sorte d'interface ParallelFunction que les outils de classe générique, mais pour accéder à la dactylographiée réelle propriété des données que vous auriez reste à faire casting de l'interface à ParallelFunction . Peut-être pourriez-vous mettre en place un modèle de visiteur? – BrandonAGr

Répondre

1

dans de telles situations où les types génériques sont exposés à des infrastructures non génériques, je présente une interface non générique:

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; } 
} 

Vous voyez, j'ai changé la conception un peu pour exposer moins des choses que la classe fait. L'interface peut exposer des bits non génériques "CacheResult". Votre assistant peut maintenant travailler à partir de l'interface en invoquant la méthode Cacheresult. En dehors de l'assistant, vous pouvez toujours avoir vos implémentations génériques.

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

Utilisez une variante de l'interface IParallelFunc<out T> implémentée par ParallelFunc<T>. Ensuite, un IParallelFunc<int> et un IParallelFunc<string> pourraient tous deux être généralisés à un IParallelFunc<object> et être traités par votre méthode.

+0

Merci pour le conseil. Mais le problème est que je ne peux pas encore l'ajouter à une liste de type Liste >. – gsharp

+0

^this - seulement si .NET 4 –

+0

jup. je suis sur .net 4. ça ne fonctionne pas avec List > – gsharp