Does MEF Support Customized CTOR? - mef

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.

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);
}

Define Generic List from 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;
}
}

Why can't EF assign my child collection when the constructor is private?

I have an entity that looks like this
public class SlideSet {
public SlideSet(string name) : this() {
Name = name
}
public SlideSet() {
Params = new HashSet<SlideSetParameter>();
}
[Required]
public string Name { get; set; }
public virtual ICollection<SlideSetParameter> Params { get; set; }
}
I just noticed that I'm not actually using the second constructor ever and that it actually makes no sense in my domain so I made it private. All of a sudden the Params array stopped loading and always gives me a length of 0. What's going on? In order for it to load I need my constructor to be at least protected. Why?
One of the conditions for EF to be able to create proxies (necessary for lazy loading) is
The class must have a public or protected parameter-less constructor.
From here (an old link, but this part still applies)
The proxy is a derived type and it must be able to call the parameterless constructor of the base type.
You need to have your default constructor set to public, as that is what Entity Framework is going to use to create your objects. Having it as private, it is unable to initialize the Params property, and therefor is trying to add any SlideSetParameters to a null object.

EF: Many tables with the same column - can I access to it without copying the code?

I have some tables which stores the file's data, e.g TabA, TabB, TabC, ... TabX. Each of them has the same column FileTypeID.
For each table I need to use the extension method to get the rows depending of the condition of the FileTypeID column. To do so, I have an extension method like that:
public static class FilesTab_Extenders
{
public static IList<TabA> GetSpecificFiles(this EntityCollection<TabA> mc)
{
///
}
}
but, I don't want mindlessly clone the same code for the rest of tables. The only difference will be the parameter - this EntityCollection<TabB>, this EntityCollection<TabC> etc. So, is it somehow possible to make the universal code for that scenario ?
To me the easiest way to do this would be to use an interface. You would then have your partial classes implement this interface and use it in your extention method:
public interface IFileTypeable
{
Guid FileTypeId { get; set;}
}
Now you would create partial class files for each of your TabA, TabB, TabC, ... TabX that follow this template:
namespace MyDBContextNamespace
{
public partial class TabA : IFileTypeable
{
// no need to do anything, the property is already implemented on the original class file.
}
public partial class TabB : IFileTypeable
{
// no need to do anything, the property is already implemented on the original class file.
}
}
Finally your extention method would be changed to look like this:
public static IList<IFileTypeable> GetSpecificFiles(this EntityCollection<IFileTypeable> mc)
{
foreach (var item in mc)
{
Guid fileTypeId = item.FileTypeId;
}
}

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.