How can you implement an interface with a generic method? - c#

Consider the following classes and interfaces:
interface INameable
{
string Name { get; }
}
interface IRepository<T>
{
void Add(T obj);
IEnumerable<T> Values { get; }
}
class Person : INameable
{
public string Name { get; set; }
public int Age { get; set; }
}
class Car : INameable
{
public string Name { get; set; }
public string Model { get; set; }
}
I now would like to create a Repository class that implements both IRepository<Car> and IRepository<Person>. Here is a sample implementation:
class Repository : IRepository<Car>, IRepository<Person>
{
Dictionary<string, object> values = new Dictionary<string, object>();
void AddValue(INameable o)
{
values.Add(o.Name, o);
}
IEnumerable<T> ValuesOfType<T>()
{
return values.Values.OfType<T>();
}
void IRepository<Car>.Add(Car obj)
{
AddValue(obj);
}
void IRepository<Person>.Add(Person obj)
{
AddValue(obj);
}
IEnumerable<Car> IRepository<Car>.Values
{
get { return ValuesOfType<Car>(); }
}
IEnumerable<Person> IRepository<Person>.Values
{
get { return ValuesOfType<Person>(); }
}
}
This works exactly as expected. However, it is very repetitive; the code for the implementation of IRepository<Person> and IRepository<Car> is nearly exactly the same.
What I would like to do is implement IRepository for all T where T is a INameable. I tried this:
class Repository2 : IRepository<Car>, IRepository<Person>
{
// same as before
Dictionary<string, object> values = new Dictionary<string, object>();
void AddValue(INameable o)
{
values.Add(o.Name, o);
}
IEnumerable<T> ValuesOfType<T>()
{
return values.Values.OfType<T>();
}
// using generics to implement both the interfaces
void Add<T>(T obj) where T : INameable
{
AddValue(obj);
}
void Values<T>() where T : INameable
{
return ValuesOfType<T>();
}
}
However I get errors like:
ConsoleApp.Repository2' does not implement interface member 'ConsoleApp.IRepository<ConsoleApp.Car>.Add(ConsoleApp.Car)'
I'm not sure why the Add<T> and Vales<T> methods aren't being matched - both T's can be set to Person and Car, and then they would exactly match the method type needed.
Finally, I tried:
class Repository3 : IRepository<T> where T is INameable {... }
However, I get an error "Constraints are not allowed on non-generic declarations".
What is the best way of solving this problem?
Note that I am doing this as a method to simply access to a DbContext class (which has references to every table in the application), so instead of passing the full database to each controller, I only pass the data that is needed. I was doing this to better separate the database from the rest of the app, and to improve testability. If there is a better way of doing this that could also help.

You could have an abstract class with the implementation and then just inherit it for specific types.
public interface INameable
{
string Name { get; }
}
public interface IRepository<T>
{
void Add( T obj );
IEnumerable<T> Values { get; }
}
public class Person : INameable
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Car : INameable
{
public string Name { get; set; }
public string Model { get; set; }
}
public abstract class AbstractRepository<T> : IRepository<T>
where T : INameable
{
// same as before
Dictionary<string, object> values = new Dictionary<string, object>();
void AddValue( INameable o )
{
values.Add( o.Name, o );
}
IEnumerable<T> ValuesOfType<T>()
{
return values.Values.OfType<T>();
}
// using generics to implement both the interfaces
public void Add( T obj )
{
AddValue( obj );
}
public IEnumerable<T> Values
{
get
{
return ValuesOfType<T>();
}
}
}
public class CarRepository : AbstractRepository<Car> { }
public class PersonRepository : AbstractRepository<Person> { }

In my experience, it is much easier that all the entities, that are to be added to some repository, conform to some interface, say IBaseObject:
interface IRepository
{
void Add(IBaseObject obj);
IEnumerable<IBaseObject> Values { get; }
}
This generally ends up being a good solution because in IBaseObject you could have an identifier so you know when to add or an update an existing record.
update:
Another approach is to use the following pattern, again still relying on IBaseObject:
interface IRepository
{
void Add(T obj) where T : IBaseObject;
IEnumerable<T> GetValues() where T : IBaseObject;
}

I think, you should create class that creates repositories. Something like this:
class Repository<T> : IRepository<T>
where T : INameable
{
Dictionary<string, T> values = new Dictionary<string, T>();
void AddValue(T o)
{
values.Add(o.Name, o);
}
public void Add(T obj)
{
AddValue(obj);
}
public IEnumerable<T> Values
{
get { return values.Values; }
}
}
class UnitOfWork
{
private readonly Dictionary<Type, object> _repositories = new Dictionary<Type, object>();
public IRepository<T> GetRepository<T>()
where T : INameable
{
object repository;
if (!_repositories.TryGetValue(typeof (T), out repository))
{
repository = new Repository<T>();
_repositories[typeof (T)] = repository;
}
return (IRepository<T>)repository;
}
}
And use it like that:
var unitOfWork = new UnitOfWork();
unitOfWork.GetRepository<Car>().Add(new Car {Name = "Audi"});
unitOfWork.GetRepository<Car>().Add(new Car { Name = "BMW" });
foreach (var car in unitOfWork.GetRepository<Car>().Values)
Console.WriteLine(car.Name);

Related

Generalize a generic class

I have written a Collection like this:
class AnimalCollection<TValue> where TValue : Animal, new()
{
void Add(TValue value){};
void AddNew()
{
Add(new TValue());
}
}
I have some Classes which are derived from Animal:
class Animal
{
string Name;
}
class Fish : Animal
{
Fish(){};
}
class Mammal : Animal
{
Mammal(){};
}
As next i want to treat all collections the same way.
static void Main(string[] args)
{
var FishAquarium = new AnimalCollection<Fish>();
var MammalEnclosure = new AnimalCollection<Mammal>();
foo(FishAquarium);
foo(MammalEnclosure);
}
Question 1: I want to pass every AnimalCollection, which type need 'zoo'?
static void foo(AnimalCollection<Animal> zoo)
{
foreach(var animal in Zoo)
Console.WriteLine(animal.Name);
zoo.AddNew();
}
Question 2: What is the best practice to generalize a generic class?
Update:
More specific, i have a class which get any AnimalCollection.
class ZooController
{
public AnimalCollection<Animal> Animals{get; set;}
}
Generics would work:
static void foo<T>(AnimalCollection<T> zoo) where T : Animal, new()
{...}
However, it is usually not a good idea to roll your own collection types - it tends to create more confusion than it helps. You may want to consider justList<T>, or IList<T> at a push.
You say you don't want to use generics; that is IMO a silly decision since they solve exactly this problem, but you can also use covariance; if you have:
interface IAnimalCollection<out TValue> : IEnumerable<TValue>
{
void AddNew();
}
and:
class AnimalCollection<TValue> : IAnimalCollection<TValue>
where TValue : Animal, new()
{...}
then you can use:
static void foo(IAnimalCollection<Animal> zoo)
{
foreach (var animal in zoo)
Console.WriteLine(animal.Name);
zoo.AddNew();
}
and your code:
var FishAquarium = new AnimalCollection<Fish>();
var MammalEnclosure = new AnimalCollection<Mammal>();
foo(FishAquarium);
foo(MammalEnclosure);
will work fine; but - this is making work for no reason - simple generics via the foo<T> method shown above is simpler and more direct.
Try this approach:
class Program
{
static void Main(string[] args)
{
List<IAnimal> animals = new List<IAnimal>() { new Animal("Fuffy"), new Fish("Fishy"), new Mammal("Mommy") };
OutputAnimalsNames(animals);
}
private static void OutputAnimalsNames(List<IAnimal> animals)
{
foreach (IAnimal animal in animals)
{
Console.WriteLine(animal.Name);
}
}
}
public interface IAnimal
{
Guid Guid { get; }
string Name { get; }
}
public class Animal : IAnimal
{
public Guid Guid { get; private set; }
public string Name { get; set; }
public Animal(string name)
{
this.Name = name;
this.Guid = Guid.NewGuid();
}
}
public class Fish : Animal
{
public Fish(string name) : base(name)
{
}
}
public class Mammal : Animal
{
public Mammal(string name) : base(name)
{
}
}

Implement an interface method with a concrete class

I have the following interfaces, one for the entity and one for some logic:
public interface IItem
{
int Id { get; set; }
}
public interface IGenerator
{
IList<IItem> Generate();
}
and implementation:
public class ItemA : IItem
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ItemAGenerator : IGenerator
{
public IList<ItemA> Generate()
{
// do stuff
return List<ItemA>;
}
}
That implementation did not work, it says that it does not have the matching return type, so I also tried:
public class ItemAGenerator : IGenerator
{
public IList<IItem> Generate()
{
// do stuff
return List<ItemA>;
}
}
it does not work as well, it says: cannot implicitly convert type List<IItem> to List<ItemA>.
How to make it work? what am I missing here.
Just create the list as a List<IItem> but add ItemA's to it.
public class ItemAGenerator : IGenerator
{
public IList<IItem> Generate()
{
var list = new List<IItem>();
list.Add(new ItemA());
return list;
}
}
Just make IGenerator generic. Then you can specify the type that will be returned.
public interface IGenerator<T> where T : IItem
{
IList<T> Generate();
}
public class ItemAGenerator : IGenerator<ItemA>
{
public IList<ItemA> Generate()
{
// do stuff
return List<ItemA>;
}
}

How to make the Type in lamba expression be the type of derived class from a generic base class

I have the following code:
public abstract class EntityMapperBase<T>
{
protected void Map(string columnName, Func<EntityMapperBase<T>, object> func)
{
_mappings.Add(columnName, func);
}
protected object GetValueForColumn(string columnName)
{
return _mapping[columnName](this);
}
}
public class PersonMap: EntityMapperBase<PersonMap>
{
public string Name { get; set; }
public PersonMap()
{
Map(x => ((PersonMap)x).Name);
}
}
I would ideally not want to have to cast x to the PersonMap class.
How can I achieve that?
What you are looking for is probably this:
public abstract class Base<T>
{
public void Test(Func<Base<T>, object> func)
{
func(this);
}
}
Or if you use T as a property inside your Base object:
public abstract class Base<T>
{
public T MyAwesomeProperty { get; private set; }
public void Test(Func<T, object> func)
{
func(MyAwesomeProperty);
}
}
T != Base<T>
Why use generics? You can add functions without the type and do the same you are trying to do..
public abstract class EntityMapperBase
{
protected void Map(string columnName, Func<object> func)
{
_mappings.Add(columnName, func);
}
protected object GetValueForColumn(string columnName)
{
return _mapping[columnName]();
}
}
public class PersonMap: EntityMapperBase
{
public string Name { get; set; }
public PersonMap()
{
Map(() => this.Name);
}
}

Modular application generic DTO

I want to pass a list/dictionary of generic parameter (that can be different types in the same collection) to a method in a modular application.
I hope my code can explain it better.
The interfaces:
public interface IField
{ }
public interface IField<T> : IField
{
T Value { get; }
}
The implemented class:
public class Field<T> : IField<T>
{
public Field(T value)
{
Value = value;
}
public T Value { get; set; }
}
Now I can create a Dictionary with my parameters and call a method that is implemented in a different assembly not referenced (I get it using reflection):
static void Main(string[] args)
{
var dicFields = new Dictionary<string, IField>();
dicFields.Add("param1", new Field<string>("Hello"));
dicFields.Add("param2", new Field<int>(15));
MyMethod(dicFields);
}
Now, in 'MyMethod', I want to get the value for a specific parameter in the dictionary:
public void MyMethod(IDictionary<string, IField> parameters)
{
var param2 = parameters["param2"];
}
The problem is that 'param2' has not the property Value (generic type) because I used the IField interface to define the dictionary elements and in 'MyMethod' we can't know the right implementation of the parameter.
Any suggestion to achieve my goal?
Generics do not work this way.
To get the Generic Types, you need to use the IField<T> interface in your dictionary and your method.
However, you aren't going to be able to mix types because when you create an instance of a class you IField will be restricted to only T:
public interface IField
{
}
public interface IField<T> : IField
{
T Value { get; }
}
public class Field<T> : IField<T>
{
public Field(T value)
{
Value = value;
}
public T Value { get; set; }
}
public void Generic()
{
var dicFields = new Dictionary<string, IField<string>>();
dicFields.Add("param1", new Field<string>("Hello"));
dicFields.Add("param2", new Field<string>("Hello"));
MyMethod<String>(dicFields);
}
public void MyMethod<T>(IDictionary<string, IField<T>> parameters)
{
var param2 = parameters["param2"].Value;
}
If you wanted to mix types you would need to use IField which will require you to box and unbox your types:
public interface IField
{
}
public interface IField<T> : IField
{
T Value { get; }
}
public class Field<T> : IField<T>
{
public Field(T value)
{
Value = value;
}
public T Value { get; set; }
}
public void Generic()
{
var dicFields = new Dictionary<string, IField<object>>();
dicFields.Add("param1", new Field<object>("Hello"));
dicFields.Add("param2", new Field<object>(2));
MyMethod<object>(dicFields);
}
public void MyMethod<T>(IDictionary<string, IField<T>> parameters)
{
var param2 = parameters["param2"].Value;
}
While it is considered bad practice, you could use a Dictionary<string, Dynamic>
Dictionary<string, dynamic> dict = new Dictionary<string, dynamic>();
dict.Add("value1", "a");
dict.Add("value2", 2);
dict.Add("value3", 3);
int result = dict["value2"] + dict["value3"];
One way to manage what you're trying to do is to add access methods to IField that will allow you to get an object value and the type.
public interface IField
{
object GetValue { get; }
Type GetValueType();
}

Factory pattern with 4 layer architecture

In my project i have 4 layers presentation,BL,DL, and dataObjects. i want to implement abstract factory pattern to get the object i want(doctor/Engineer). Is the code below implementing factory pattern?
public interface IProfessional //The Abstract Factory interface.
{
IProfession CreateObj();
}
// The Concrete Factory class1.
public class DocFactory : IProfessional
{
public IProfession CreateObj()
{
return new Doctor();
}
}
// The Concrete Factory class2.
public class EngFactory : IProfessional
{
public IProfession CreateObj()
{
// IMPLEMENT YOUR LOGIC
return new Engineer();
}
}
// The Abstract Item class
public interface IProfession
{
}
// The Item class.
public class Doctor : IProfession
{
public int MedicalSpecialty
{
get; set;
}
public int AreaofExpertise
{
get; set;
}
}
// The Item class.
public class Engineer : IProfession
{
public string Title{
get;set;
}
public int AreaofExpertise
{
get; set;
}
}
// The Client class.
public class AssignProfession
{
private IProfession _data;
public AssignProfession(DataType dataType)
{
IProfessional factory;
switch (dataType)
{
case DataType.Doc:
factory = new EngFactory();
_data = factory.CreateObj();//from here i will get engineer
break;
case DataType.Eng:
factory = new DocFactory();
_data = factory.CreateObj();//from here i will get doctor
break;
}
}
public IProfession GiveProfessional()
{
return _data;
}
}
//The DataType enumeration.
public enum DataType
{
Doc,
Eng
}
Your code does implement the pattern but not to the full extent which C# allows, in other words - you are not using the important benefits of the C# language.
Here is an example of how you can do it better:
class Program
{
static void Main(string[] args)
{
var myEngineer = ProfessionFactory.CreateProffession<Engineer>();
var myDoctor = ProfessionFactory.CreateProffession<Doctor>();
myEngineer.EnginerringStuff();
myDoctor.HealingPeople();
var myEngineer2 = (Engineer)ProfessionFactory.CreateProffession("Engineer");
//using the other method I still have to cast in order to access Engineer methods.
//therefore knowing what type to create is essential unless we don't care about engineer specific methods,
//in that case we can do:
var myEngineer3 = ProfessionFactory.CreateProffession("Engineer");
//which is useless unless we start involving reflections which will have its own price..
}
public interface IProfessionFactory
{
IProfession CreateObj();
}
public interface IProfession : IProfessionFactory
{
string ProfessionName { get; }
}
public abstract class ProfessionFactory : IProfessionFactory
{
public abstract IProfession CreateObj();
public static T CreateProffession<T>() where T:IProfessionFactory, new()
{
return (T)new T().CreateObj();
}
public static IProfession CreateProffession(object dataObj)
{
if (dataObj == "Engineer")
return CreateProffession<Engineer>();
if (dataObj == "Doctor")
return CreateProffession<Doctor>();
throw new Exception("Not Implemented!");
}
}
public class Engineer : IProfession
{
public string ProfessionName
{
get { return "Engineer"; }
}
public IProfession CreateObj()
{
return new Engineer();
}
public void EnginerringStuff()
{}
}
public class Doctor : IProfession
{
public string ProfessionName
{
get { return "Doctor"; }
}
public IProfession CreateObj()
{
return new Doctor();
}
public void HealingPeople()
{}
}
}
It does seem to have all elements of the pattern, however your IProfession is empty. I am going to assume that is just a placeholder and you are going to fill it in with some methods that represent a behavior that is common to all professions.
Contrast that with the example given in Allen Holub's book
He mentions Collection as the AbstractFactory, Iterator as the abstract product, Tree as the concrete factory and the iterators that are returned as concrete products.

Categories

Resources