Reputation: 1704
I want to make code that is as DRY as possible. The architecture I'm using has various pieces of data: Channel, User, Process, etc. Each has a public Id
string property. I'm currently abstracting out a lot of the business logic with:
using System;
using System.Collections.Generic;
using Vert.Slack;
namespace Vert.Interfaces
{
public abstract class DataSource<T> : IDataSource<T>
{
protected Dictionary<string, T> _items;
public DataSource()
{
_items = new Dictionary<string, T>();
}
public abstract bool Register(T item);
public T LookupUsing<String>(string key)
{
T item = default(T);
item = _items[key];
return item;
}
public IEnumerable<T> List(int? limit)
{
List<T> items;
if(!limit.HasValue)
{
items = new List<T>(_items.Values);
}
else
{
items = new List<T>(limit.Value);
items.AddRange(_items.Values);
}
return items;
}
public abstract T LookupUsing<RtmEvent>(Slack.RtmEvent rtmEvent);
public abstract T LookupUsing<Message>(Slack.Message message);
}
}
I want to make Register
generic, because I'm currently using this code on each of my classes that extends DataSource (where the only difference is Im
, User
, Channel
, etc.) :
public override bool Register(Im im)
{
if(!_items.ContainsKey(im.Id))
{
_items.Add(im.Id, im);
}
return true;
}
I'm currently running into problems because my first attempt was to change T
to a new type I defined as IData
:
namespace Vert.Data
{
interface IData
{
string Id { get; set; }
}
}
However this seems to confuse the compiler, because when I try to use the above Register
in the new abstract DataSource class I get the compiler error:
'IData' does not contain a definition for 'Id' and no extension method 'Id' accepting a first argument of type 'IData' could be found (are you missing a using directive or assembly reference?)
There's gotta be a way to do this generically. What am I doing wrong?
Upvotes: 2
Views: 482
Reputation: 652
You've just exchanged <T> with <IData>? That won't work as you've just changed name of generic type nothing more.
Instead try telling compiler that generic <T> should implement IData interface:
public abstract class DataSource<T> : IDataSource<T> where T : IData
Upvotes: 5