Define Generic List from interface - interface

This may be an easy answer, but I'm creating what I thought was a simple interface that is to contain a definition for a generic list. Basically just something that says "create a generic list" like below:
public static List<UserControl> ViewList = new List<UserControl>();
This is proving more difficult than I expected. Maybe I'm going about it wrong? Each definition I try results in the expected list being a property or a method. For example, I've tried the below with no luck
//FirstTry
public interface IAddToViewList
{
List<UserControl> ViewList();
}
//Second
public interface IAddToViewList
{
List<UserControl> ViewList { get; set; }
}
Also I'm not sure if it's possible to include that the list should be static, I'm having trouble finding anyone with a question matching these requirements, maybe because it's just not possible or I'm thinking about it the wrong way?

Interfaces are collections of abstract methods. This means that you are unable to add class variables to them.
What you would need to functionally accomplish this is an Abstract Class.
public abstract class AddToViewList
{
List<UserControl> ViewList;
}
However, all you need to do is define a method that returns a list
public interface IAddToViewList
{
public List<UserControl> createViewList();
}
This will ensure that every class that implements IAddToViewList also has the createViewList() method. Now, in this case, UserControl would have to be a defined class and so this is a list of UserControl objects, not a "Generic List".
To make the list generic you have add the diamond after the interface name:
public interface IAddToViewList<UserControl>
{
public List<UserControl> createViewList();
}
then when you are implementing your class it would look like this
public class Foo implements IAddToViewList<String>
{
public List<String> createViewList(){
// TODO
return null;
}
}

Related

Entity Framework Set with Generic Class

Ok, I might be punching above my pay grade here, but I'm trying to create a generic CRUD routine for and EF project. I've got most of it working but I'm flailing around on one point.
Normally you do something like this to add an entity through a context-
DBContext.MyClass.Add( p ); // p = instance of MyClass
That works fine, but since in a global method to handle all adds regardless of what class they are I'm passing in a Model as an object it would look more like this-
DBContext<whateverobject>.Add(whateverobject); // my objects is an object param passed into the method
I've tried doing a bunch of typeofs and there where T : class stuff but I'm having no luck. Any pointing in the right direction would help me out.
I'm using EF Core 2 so my options might also be more limited than EF 6.
Thanks.
The method you're looking for is DbContext's Set<T>()
Your generic repository for your generic CRUD would look something like this:
public class Repo<T> where T: class
{
private readonly DbSet<T> _set;
public Repo(DbContext dbContext)
{
_set = dbContext.Set<T>();
}
public void Add(T entity) => _set.Add(entity);
}
This example includes a maybe unusual thing:
where T: class: we have to specify that T has to be a reference type because DbSet<T> expects T to be a reference type
For generic querying you might want to use extension methods.
In order to implement a ById method you'd have to specify that the type T must have an Id property using an interface. That would look something like this:
public interface IEntity
{
int Id { get; set; }
}
public class User : IEntity
{
public int Id { get; set; }
}
public static class DbSetExtensions
{
public static T ById<T>(this DbSet<T> dbSet, int id) where T: class =>
dbSet.FirstOrDefault(entity => entity.Id == id);
}

Entity Framework code first Inheritance Issue

I have code first implementation for flowing hierarchy,
BaseContact{
Public int Id{get;set;}
public string Name{get;set;}
//..
}
Person:BaseContact{
public string Designation{get;set;}
//..
}
Company:BaseContact{
public int NumOfEmployees{get;set;}
//..
}
I want to identify person or company with by using only the Id value? Currently I am using reflection to identify whether it is a person or company. Is there any other way to identify it without doing too much?
Without seeing how you initialised your classes I'm going to assume you have a table per concrete type approach.
You can't do it just from the ID, as you don't know which table the ID belongs to. ID 2 in "Person" table is a different entity to ID 3 in "Company". The only practical way to identify only from an ID is using a Table per Hierarchy approach and inspecting the type descriptor.
Some good references
http://weblogs.asp.net/manavi/archive/2011/01/03/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-3-table-per-concrete-type-tpc-and-choosing-strategy-guidelines.aspx
http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx
You can also use a simple is statement instead of reflection. Ie if (entity is Company)
In your BaseContact (assume it is an abstract class) add abstract property which will be implemented by other two classes.Use Enum to identify the property type as follows.
public enum MyType
{
Person,
Company,
};
public abstract class BaseContact{
public abstract MyType ContactType{get;}
}
public class Person:BaseContact
{
public override MyType ContactType
{
get
{
return MyType.Person;
}
}
}
public class Company:BaseContact
{
public override MyType ContactType
{
get
{
return MyType.Company;
}
}
}
Use your BaseContact repository to retrieve entities and use enum for type separation.

Asp.Net Mvc templated helpers with interface types

I would like to use the Asp.net MVC templated helpers functionality to generate a standard UI for my objects throughout my application, but I've run into a significant issue:
I do not directly pass class types from my controllers into their views. Instead, I pass interface types.. with the actual implementation of the Model wrapped up in a Mongo or NHibernate specific class in an indirectly referenced project.
For discussion, my objects look like:
public interface IProductRepository {
IProduct GetByName(string name);
}
public interface IProduct {
string Name { get; set; }
}
public class NHibernateProductRepository : IProductRepository {
public IProduct GetByName(string name) {
/* NHibernate Magic here */
return nhibernateFoundProduct;
}
}
public class NHibernateProduct : IProduct {
public virtual Name { get; set; }
}
public class ProductController : Controller {
public ProductController(IProductRepository productRepo) {
_ProductRepo = productRepo;
}
public ActionResult Index(string name) {
IProduct product = _ProductRepo.GetByName(name);
return View(product);
}
}
Is it possible to use interface types with the Editor.For() syntax? Are there any problems or sticking points that I need to be aware of?
I have an EditorTemplate\IProduct.ascx file available. At this time, I can't seem to get that template to be rendered without hardcoding the "IProduct" name into the Editor.For() call. I would prefer this type of 'Convention over Configuration'....
The templates helpers will use the runtime type of the object for the name. In this case you should name the file NHibernateProduct.ascx
If you don't know the name of the type at design time than you could write a helper method that would inspect the object instance and walk the list of interfaces that a particular type is implementing and return a name based on that. Then you would call the appropriate override to EditorFor that takes the string "templateName" parameter.
I have decided to use an approach with a ViewModel native to the Web project that implements the IProduct interface.

IoC in complex environment

Here is the situation:
ICategorized is used by ICategoryService to manage categories.
public interface ICategorized
{
ICategory Category { get; set; }
}
Then some class implements ICategorized.
public class Cart : ICategorized
{
...
ICategory Category {
get {
return _categoryService.GetItemCategory(...)
}
set {
_categoryService.SetCategoryForItem(...);
};
}
...
}
So, what is the best solution to set _categoryService implementation?
Through constructor or property injection?
Using of constructor can lead to very complex constructor like
public class Cart : ICategorized. ITagged, ISecured, IMediaSupport {
public Cart(ICategoryService cs, ITagService ts, ISecurityService ss, IMediaService ms) {...}
...
}
I doubt this is a good design. Any ideas?
What would be your suggestion?
I can give to CartService responsibility of ICategoryService but in that case I can't use Lazy loading. Something like
public class CartService : ICartService {
public CartService(ICategoryService cs) {...}
...
}
I favor constructor injection over property injection, mainly because it makes explicit what services the component requires. If you use an IoC-container you wouldn't have to worry about the constructor getting too complicated since you never have to use the constructor, only the container does.
Property injection could be used for non-required services.
By the way; generally speaking, very long constructor signatures probably means that your class does not adhere to the single responsibility principle and perhaps it should be refactored into two or more separate classes.

Does MEF Support Customized CTOR?

It looks like that MEF framework creates objects which have default CTOR. How about customized CTOR, or Constructor with parameters? For example:
[Export (typeof(IInterface1))]
public class MyClass : IInterface1
{
public MyClass(int id) {....}
....
}
If not, one way I can think is to pass object as parameters to CTOR. For example:
public Interface IParameterID {
public int Id { get; private set; }
...
}
Then the CTOR will be:
public MyClass([Import(typeof(IParameter))] IParameterID id)
{ ... }
Not sure if it is possible to add attribute to CTOR's parameters? And the next question is that if MEF will automatically create an instance of IParameter and inject it to the CTOR's parameter?
Yes, this is possible. Just put an [ImportingConstructorAttribute] on the constructor you would like to use. The parameters will automatically be treated as imports, but if you need to change the contract name on them you can also put an import attribute on them.