Variant Generic Interfaces - c#-4.0

I have a generic interface, and a class implementing that interface with a concrete type parameter. I also have a generic class using the generic interface as its type constraint, but the type parameter is restricted to be a subclass of a certain base class. I want to instance the generic class with the class implementing that interface but have a problem of converting the class to that interface. The following code illustrates all the classes I mentioned:
The base class:
class DomainBase
{
}
The class used as the type parameter in the interface
class Person : DomainBase
{
}
The generic interface:
public interface IRepository<T> where T : class
{
IEnumerable<T> Fetch();
T Persist(T item);
}
The class implementing the generic interface:
class PersonRepository : IRepository<Person>
{
public IEnumerable<Person> Fetch()
{
...
}
public Person Persist(Person item)
{
...
}
}
The generic class using the generic interface:
class DomainBaseViewModel<Repository>
where Repository : IRepository<DomainBase>, new()
{
private Repository repository = new Repository();
private ObservableCollection<DomainBase> items;
}
However, the following line can't get compiled because PersonRepository is unable to be converted to IRepository<DomainBase>:
var viewModel = new DomainBaseViewModel<PersonRepository>();
Although I can solve this issue by covariance but it disallows the use of the type parameter in parameter lists:
public interface IRepository<out T> where T : class
{
...
T Persist(object item);
}
class PersonRepository : IRepository<Person>
{
public Person Persist(object item)
{
...
}
}
So I have to convert the parameter to Person, which compromises type safety.
Is there a better way to allow covariance and the use of type parameter in parameter lists in this case?

No - the whole point of the restriction on covariance is that it guarantees safety. A PersonRepository isn't an IRepository<DomainBase> because you can't ask it to persist any arbitrary DomainBase object. What would you expect this code to do?
class Product : DomainBase {}
...
IRepository<DomainBase> repository = new PersonRepository();
repository.Persist(new Product());
PersonRepository doesn't know how to persist Product values.
If in some cases you only need the "read" parts of the repository interface, you could always call that out explicitly:
public interface IRepositoryReader<out T>
{
IEnumerable<T> Fetch();
}
public interface IRepository<T> : IRepositoryReader<T>
{
T Persist(T item);
}
Then your DomainBaseViewModel class could be:
class DomainBaseViewModel<TRepository>
where TRepository : IRepositoryReader<DomainBase>, new()
{
private TRepository repository = new TRepository();
private ObservableCollection<DomainBase> items;
}
That doesn't work if you want your DomainBaseViewModel to persist items as well though. In that case, perhaps it should be generic in the type of model as well:
class DomainBaseViewModel<TRepository, TEntity>
where TRepository : IRepository<TEntity>, new()
{
private TRepository repository = new Repository();
private ObservableCollection<TEntity> items;
}
Then:
var viewModel = new DomainBaseViewModel<PersonRepository, Person>();

Related

Differences between Abstract Factory Pattern and Factory Method,confused by one case

The main difference between a "factory method" and an "abstract factory" is that the factory method is a single method, and an abstract factory is an object. But, sometimes I can't say what it is,for example
class Product{
}
interface Facotory{
public Product create();
}
class FactoryA implements Facotory{
public Product create() {
return null;
}
}
class FactoryB implements Facotory{
public Product create() {
return null;
}
}
Can you tell me it is factory method or abstract factory?Thank you!
IMO, Your current example above is Factory Method.
As you have defined an interface (Factory) with a factory method (create) that allows sub classes (FactoryA and FactoryB) to decide which class to instantiate (Product derived classes).

Retrieving an Enum through a class and its descendants

I have a class that I've defined, and I have a number of child classes derived from it. The parent class has an enum (let's call it 'Barf'). Each descendant ALSO has an enum with the same name but not the same values. What I'm trying to figure out how to do is write a method in the ancestor class that gets the version of Barf for the actual class of the instantiated object. So if I create an instance of Ancestor, I'd like to have this method process the entries for Ancestor.Barf . If I create an instance of one of the child classes of Ancestor, I'd like to have the method process Childx.Barf values.
Obviously this is going to be a Reflection solution, but my reflection skills are pretty sparse. Any help?
Just for the fun of it, here is a possible approach:
public class Ancestor {
public enum Caffeine {
Tea,
Coffee
}
public void ProcessValues() {
var type = GetType();
var nestedEnums = from t in type.GetNestedTypes()
where t.IsEnum
select t;
var nestedEnum = nestedEnums.Single();
foreach(var val in Enum.GetValues(nestedEnum)) {
Console.WriteLine("Drinking {0}", val);
}
}
}
public class Descendant : Ancestor {
public new enum Caffeine {
Jolt,
RedBull
}
}
// The following prints:
// Drinking Jolt
// Drinking RedBull
Ancestor x = new Descendant();
x.ProcessValues();
Of course, you could achieve the same thing using polymorphism:
public class Ancestor {
public enum Caffeine {
Tea,
Coffee
}
protected virtual Type GetNestedEnum() {
return typeof(Ancestor.Caffeine);
}
public void ProcessValues() {
var nestedEnum = GetNestedEnum();
foreach(var val in Enum.GetValues(nestedEnum)) {
Console.WriteLine("Drinking {0}", val);
}
}
}
public class Descendant : Ancestor {
public new enum Caffeine {
Jolt,
RedBull
}
protected override Type GetNestedEnum() {
return typeof(Descendant.Caffeine);
}
}
As Justin Morgan has pointed out however, having the need for such a construct may be an indication of an underlying design issue in your code.

Does not contain a constructor that takes 0 arguments

I get an error stating "Products does not contain a constructor that takes 0 arguments" from the following code:
public class Products
{
string id;
string name;
double price;
int soldCount;
int stockCount;
public Products(string id, string name, double price,
int soldCount, int stockCount, double tax)
{
this.id = id;
this.name = name;
this.price = price;
this.soldCount = soldCount;
this.stockCount = stockCount;
}
}
//I have got some get and set values for the code above
//but it would have been too long to put in here
public class FoodProducts : Products
{
public FoodProduct()
{
Console.WriteLine("This is food product");
}
public void Limit()
{
Console.WriteLine("This is an Attribute of a Product");
}
}
Several rules about C# come into play here:
Each class must have a constructor (In order to be, well constructed)
If you do not provide a constructor, a constructor will be provided for you, free of change, automatically by the compiler.
This means that the class
class Demo{}
upon compilation is provided with an empty constructor, becoming
class Demo{
public Demo(){}
}
and I can do
Demo instance = new Demo();
If you do provide a constructor (any constructor with any signature), the empty constructor will not be generated
class Demo{
public Demo(int parameter){}
}
Demo instance = new Demo(); //this code now fails
Demo instance = new Demo(3); //this code now succeeds
This can seem a bit counter-intuitive, because adding code seems to break existing unrelated code, but it's a design decision of the C# team, and we have to live with it.
When you call a constructor of a derived class, if you do not specify a base class constructor to be called, the compiler calls the empty base class constructor, so
class Derived:Base {
public Derived(){}
}
becomes
class Derived:Base {
public Derived() : base() {}
}
So, in order to construct your derived class, you must have a parameterless constructor on the base class. Seeing how you added a constructor to the Products, and the compiler did not generate the default constructor, you need to explicitly add it in your code, like:
public Products()
{
}
or explicitly call it from the derived constructor
public FoodProduct()
: base(string.Empty, string.Empty, 0, 0, 0, 0)
{
}
Since Products has no constructor that takes 0 arguments, you must create a constructor for FoodProducts that calls the constructor of Products will all the required arguments.
In C#, this is done like the following:
public class FoodProducts : Products
{
public FoodProducts(string id, string name, double price, int soldCount, int stockCount, double tax)
: base(id, name, price, soldCount, stockCount, tax)
{
}
public void Limit()
{
Console.WriteLine("This is an Attribute of a Product");
}
}
If you don't want to add this constructor to FoodProducts, you can also create a constructor with no parameter to Products.
the constructor of the inherited class needs to construct the base class first. since the base class does not have a default constructor (taking 0 arguments) and you are not using the non-default constructor you have now, this won't work. so either A) add a default constructor to your base class, in which case the code of the descending class needs no change; or B) call the non-default constructor of the base class from the constructor of the descending class, in which case the base class needs no change.
A
public class Products
{
public Products() { }
}
public class FoodProducts : Products
{
public FoodProducts() { }
}
B
public class Products
{
public class Products(args) { }
}
public class FoodProducts : Products
{
public FoodProducts(args) : base(args) { }
}
some of this is explained rather OK on msdn here.
As you inherit from Products, you must call a base construct of Products in your own class.
You didn't write:base(id, name, ....) so C# assumes you call the default parameterless constructor, but it doesn't exist.
Create a default parameterless constructor for Products.
Just add
public Products()
{
}
in your products class And you will not get error
Reason:
There exists a default constructor with 0 parameter for every class. So no need to define/write it explicitly (by programmer) BUT when you overload a default constructor with your desired number and type of parameters then it becomes a compulsion to define the default constructor yourself (explicitly) along with your overloaded constructor

c# generics error: The constraints for type parameter 'T' of method ...?

Getting the following error:
Error 1 The constraints for type parameter 'T' of method
'genericstuff.Models.MyClass.GetCount<T>(string)' must match the constraints for type
parameter 'T' of interface method 'genericstuff.IMyClass.GetCount<T>(string)'. Consider
using an explicit interface implementation instead.
Class:
public class MyClass : IMyClass
{
public int GetCount<T>(string filter)
where T : class
{
NorthwindEntities db = new NorthwindEntities();
return db.CreateObjectSet<T>().Where(filter).Count();
}
}
Interface:
public interface IMyClass
{
int GetCount<T>(string filter);
}
You are restricting your T generic parameter to class in your implementation. You don't have this constraint on your interface.
You need to remove it from your class or add it to your interface to let the code compile:
Since you are calling the method CreateObjectSet<T>(), which requires the class constraint, you need to add it to your interface.
public interface IMyClass
{
int GetCount<T>(string filter) where T : class;
}
You either need to apply the constraint to the interface method as well or remove it from the implementation.
You are changing the interface contract by changing the constraint on the implementation - this isn't allowed.
public interface IMyClass
{
int GetCount<T>(string filter) where T : class;
}
You need to constrain your interface, too.
public interface IMyClass
{
int GetCount<T>(string filter) where T : class;
}

Using reflection how to find a class in an assembly which implements a generic base class and create its instance

I've a base presenter class:
public abstract class PresenterBase<T> where T : IView
{
//Some code
}
A concrete presenter class that implements this base:
public class RegistrationPresenter : PresenterBase<IRegistration>
{
//Some Code
}
A concrete presenter factory to return the instance of presenter which depends on a specific interface contract:
public class ProductPresenterFactory : PresenterFactoryBase
{
// Some code
public override PresenterBase<IView> GetPresenter(IView view, string name = "")
{
if (view == null && string.IsNullOrEmpty(name))
throw new ArgumentNullException();
return presenter;
}
}
I need to implement the GetPresenter method. The user will put the interface contract, for example of type IRegistration in the above case. This method should figure out the class that implements PresenterBase<IRegistration> and return an instance.
I did not write this with a compiler; I might have made a few mistakes.
You'll first need to get the type of the presenterbase, then we'll scour the assemble for the implementation, then call it's constructor. I'll make some assumptions as written in the code.
var genericType = typeof (PresenterBase<>).MakeGenericType(new[] { view.GetType() });
var allTypes = GetType().Assembly.GetTypes(); // I assume the class is in the same assembly.
var typeToImplement = allTypes.Single(t => t.IsSubclassOf(genericType)); // I assume there is only one implementation for the given type
var constructorToCall = typeToImplement.GetConstructors().First(); // I assume there is one constructor
var presenter = constructorToCall.Invoke(new object[0]); // I assume there is no parameter

Resources