return items.FirstOrDefault(x => x.Id == id);
The problem is: you need to tell the compiler that every x
of the sequence of items
has a property Id
.
There are two methods for this: use interfaces, or use a propertySelector function. The latter is widely used in LINQ, for instance in GroupBy.
interface IId
{
Guid Id {get; }
}
All your T
classes where you want to use GetById
should implement this interface:
class Customer : IId
{
public Guid Id {get; set;}
...
}
class Order : IId {...}
class Product : IId {...}
Your GetById seems to be in a generic class:
class ItemCollection<T> Where T : IId
{
T GetById(Guid Id)
{
...
return items.FirstOrDefault(x => x.Id == id);
}
}
Disadvantages of this method: Every class should implement this interface, and it works only with Guid Ids. If you have one class with an int Id, then you can't use the method anymore.
To overcome this problem, LINQ uses an extra parameter that says: "Hey, you should use this property as Key / Id / ..."
class ItemCollection<Tsource, Tid>
{
// Tsource: the type of items in this collection; your original T
// Tid: the type of the Id of the items; in your case: Guid
public ItemCollection(string fileName, Func<Tsource,Tid> idSelector)
{
this.fileName = fileName;
this.idSelector = idSelector;
}
readonly string fileName;
readonly Func<Tsource,Tid> IdSelector
public string ReadFile()
{
return File.ReadAllText(this.fileName);
}
public List<T> ReadItems()
{
return JsonConvert.DeserializeObject<List<T>>(this.ReadFile);
}
public Tsource GetById(Tid id)
{
return this.ReadItems()
.FirstOrDefault(item => this.IdSelector(item.Id) == id);
}
}
Usage:
const string fileName = @"D:\StorageFile.txt";
var customers = new ItemCollection<Customer, Guid>(
fileName,
customer => customer.Id)
Guid customerId = ...
Customer customer = customers.GetById(customerId);
Advantages:
- This works with all types of Ids: Guid, int, long, ...
- You've hidden that the items are in a Json file. If you decide to save them in XML or in a database, changes will be minimal
Possible improvement:
- Read the file contents only once: remember the converted items.