Reputation: 331
I am trying to create a generic Aggregate extension on Dictionary
. Something like this..
void Main(){
var foo = new Dictionary<string, Metric>();
foo["first"] = new Metric(5);
foo["sec"] = new Metric(10);
foo.Aggregate<string, Metric, int>("first", new Metric(5));
}
public class Metric : IAggregatable<int> {
public int Total { get; set; }
public Metric(int total) {
Total = total;
}
public void Aggregate(int value) {
Total += value;
}
}
public static class DictionaryExtensions {
public static void Aggregate<TKey, TValue, T>(this Dictionary<TKey, TValue> dic, TKey key, TValue value) where TValue : IAggregatable<T> {
TValue result;
if (dic.TryGetValue(key, out result))
dic[key].Aggregate(value.Total);
else
dic[key] = value;
}
}
public interface IAggregatable<T> {
T Total { get; set; }
void Aggregate(T value);
}
This works well but I have to specify the generic type arguments every time I make the call to Aggregate(...)
. This can be seen in main()
as foo.Aggregate<string, Metric, int>("first", new Metric(5));
. Is there a cleaner way to get this functionality because I would prefer to not have to specify the generic type parameters every time.
Upvotes: 0
Views: 140
Reputation: 77304
I think your interface is a bit clunky. You don't need to know the internals of your metrics. To aggregate, you only need to know what can be aggregated, not how. The how can be handled by the implementation:
using System.Collections.Generic;
namespace ConsoleApplication3
{
public class Metric : IAggregatable<Metric>
{
public int Total { get; set; }
public Metric(int total)
{
Total = total;
}
public void Aggregate(Metric other)
{
Total += other.Total;
}
}
public static class DictionaryExtensions
{
public static void Aggregate<TKey, TValue>(this Dictionary<TKey, TValue> dic, TKey key, TValue value) where TValue : IAggregatable<TValue>
{
TValue result;
if (dic.TryGetValue(key, out result))
dic[key].Aggregate(value);
else
dic[key] = value;
}
}
public interface IAggregatable<T>
{
void Aggregate(T other);
}
class Program
{
void Main()
{
var foo = new Dictionary<string, Metric>();
foo["first"] = new Metric(5);
foo["sec"] = new Metric(10);
foo.Aggregate("first", new Metric(5));
}
}
}
Upvotes: 4