How to add instance of the class which satisfies import to CompositionContainer - mef

I am facing the following problem:
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Type1).Assembly));
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Type2).Assembly));
using (CompositionContainer container = new CompositionContainer(catalog))
{
}
I need one more export:
Export[(typeof(Type3))]
The thing is that I can't include an assembly with the class which has this Export attribute. I want to tell the container that:
var myObject = new Type4();
myObject (the instance of Type4) should be exported each time the Import[(typeof(Type3))] is needed. Besides I can't mark Type4 with Export[(typeof(Type3))] and also I want the instance of the class to be used by MEF (so marking this class with Export attribute doesn't work, because I am changing myObject before I pass it to MEF and I want it to be used to satisfy Import).
Then when I try to do:
container.SatisfyImportsOnce(importer);
I expect that MEF will get all the objects from the assemblies in catalog, and for the missing Type3 it will use myObject. This should be the value when I do:
container.GetExportedValue<Type3>();
I spent one day trying different approaches: custom ExporterProvider and some sort of inheritance from Type4 to mark it with proper Export attribute but I can't get it working as I want.
I would be very grateful for help.
Thank you!

Ok, already found an answer.
First problem was that I added 2 the same AssemblyCatalogs to AggregateCatalog - don't do that.
The solution is to use CompositionBatch:
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Type1).Assembly));
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Type2).Assembly));
var myObject = new Type4();
using (CompositionContainer container = new CompositionContainer(catalog))
{
var batch = new CompositionBatch();
Export ex = CreateExport<Type3>(myObject); //Custom implementation
batch.AddExport(ex);
container.Compose(batch);
var val = container.GetExportedValue<Type3>(); //value == myObject
}
Thank you!

Related

Web Api Entity Framework

I've an error: "ExceptionMessage": "Self referencing loop detected for property 'Posto' with type 'UfficioServer.Posto'. Path '[0].Dipendente[0]'.",
when i call my web api, i need a list of Posti whit the association with Dipendente...
public List<Posto> GetAllPosti()
{
try
{
List<Posto> p = new List<Posto>();
UfficioPostiEntities1 db = new UfficioPostiEntities1();
db.Configuration.ProxyCreationEnabled = false;
var posto = db.Posto.Include("Dipendente").ToList();
var x = db.Posto.ToList();
return x;
}
can someone help me?
To avoid this error you should add the following to the Application_Start in Global.asax:
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter
.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
This is because (as per documentation)
ReferenceLoopHandling.Ignore: Json.NET will ignore objects in
reference loops and not serialize them. The first time an object is
encountered it will be serialized as usual but if the object is
encountered as a child object of itself the serializer will skip
serializing it.

How to access Number through separate class?

Hey everyone so this is something that I have always had trouble trying to accomplish or understand. So I have my main Engine class calledescapeEngine where I have a private var nScore I want to be able to access this variables through a separate class called mcPlanets but I don't know how I would accomplish this. I know how to do the opposite but not how to access a var from my main Engine class. Can anyone help me out?
I am not sure what you are trying to do, but here is an example that may help you:
Inside esacapeEngine class (main), create a public var nString and new instance of mcPlanets.
// two lines in escapeEngine.as
var nScore = 0;
var mcPlant = new mcPlanets(this);
So, when you create new mcPlanets, pass in the reference (keyword 'this' in the parentheses). Now mcPlanets knows about your main class.
And now in mcPlanets class, write this:
public class mcPlanets
{
private var escapeEngine;
public function mcPlanets(main) // 'this' = 'main'
{
escapeEngine = main;
// access nScore defined in main class
escapeEngine.nScore = 5;
}
}
In this example, nScore must be a public variable, it could be a private but you should use 'get and set' methods.

How to replace an existing collection on an Entity Frameworks POCO object

Let's say I create a new Entity and Save it as follows:
UserReport report = new UserReport() {//set the props}
manager.SaveUserReport(report)
Public UserReport SaveUserReport(UserReport report)
{
using(var context = new ReportDatabase())
{
context.UserReports.AdObject(report);
context.SaveChanges();
}
return report;
}
so far so good
I then read back the saved Report
savedReport = manager.GetUserReports(new int[] {report.Id}).FirstOrDefault();
Public List<UserReport> GetUserReports(IEnumerable<int> reportIds)
{
using (var context = new ReportDatabase())
{
var reports = from UserReport in context.UserReports
where reportIds.Contains(userReport.Id)
select userReport;
return visibleReports.ToList();
}
}
savedReport is now an attached UserReport
The UserReport object has a collection of Columns attached to it.
I want to replace the set of Columns attached with another set (that already exist in the database).
savedReport.Columns = newColumnCollection
This fails with the error "The property Columns" on type UserReport_etc' cannot be set because the collection is already set to an EntityCollection"
I've looked at this article: the problem is the same, but I cannot use that solution.
What is the correct way to tackle this?
OK - looks like it's just a case of setting the non-navigation properties to not be virtual.
That is one hell of a weird situation, given that the behaviour that is modified is of properties that remain as virtual.

Mef import into objects created after compose

I Compose the Container at startup and later on create a Instance of a object that has a Import property. This property is Null when I try to use it.
How does MEF handle objects created later on. I refuse to believe you have to instantiate all objects at startup.
You don't have to create instances as soon as you create the container, that wouldn't be any real help for anyone. How are you creating your instances? Here are some examples, given an example class:
[Export]
public class MyClass
{
[Import]
public MyOtherClass OtherClass { get; set; }
}
I could:
var myClass = container.GetExportedValue<MyClass>(); // This would automatically compose.
var myExport = container.GetExport<MyClass>();
var myClass = myExport.Value; // This would automatically compose.
var myClass = new MyClass();
container.SatisfyImportsOnce(myClass); // Manually compose your part.
Or manually wind it all together using a CompositionBatch, etc.

EF 4.0 Dynamic Proxies POCO Object Does not match target type

I am using EF 4.0 and POCO's. I stumbled across this error while inserting to records into the data base.
Property accessor 'QualityReasonID' on object 'BI.Entities.QualityReason' threw the following exception:'Object does not match target type.'
There errors occur on the Databind to a GridView after saving a new record to the database. I identified what is happening but I am not sure WHY it is occurring or If I am using EF/POCO's incorrectly. Any insight would be appreciated.
The exception is occuring because the object types in the IEnumerable are not the same.
The orginal entrys in the table are of type System.Data.Entity.DynamicProxies.QualityReason_E483AD567288B459706092F1825F53B1F93C65C5329F8095DD1D848B5D039F04}
While the new one is BI.Entities.QuailtyReason.
Here is how I insert the new object.
public void createQualityReason(QualityReason qReasons)
{
dbcontext.QualityReasons.AddObject(qReasons);
dbcontext.SaveChanges();
}
I resolved the error by changing the fetch code from:
public IEnumerable<QualityReason> fetchQualityReasons()
{
IEnumerable<QualityReason> queryReasons = dbcontext.QualityReasons.AsEnumerable();
return queryReasons;
}
to
public IEnumerable<QualityReason> fetchQualityReasons()
{
IEnumerable<QualityReason> queryReasons = from data in dbcontext.QualityReasons.AsEnumerable()
select new QualityReason
{
QualityReasonID = data.QualityReasonID,
QualityReasonName = data.QualityReasonName
};
return queryReasons;
}
So to get around the error I have to select into the POCO class explicitly each time. This feels like I am going something wrong. Any thoughts?
The error is caused because GridView does not handle polymorphic datasources when using boundfields. So you have two options
Use TemplateFields instead which can handle polymorphic datasources, this may changing some of your front end code and GridView events.
Use Linq to create a non-polymorphic databsource that the boundfields can handle
So instead of using something like ti
gvGroups.DataSource = ProductHelper.Get()
gvGroups.DataBind();
var query = from p in ProductHelper.Get()
select new {p.ProductId, p.ProductName, p.ProductDesc, p.ProductLink};
gvGroups.DataSource = query;
gvGroups.DataBind();
I don't know if the problem has been solved yet, but I've had the same problem with my (POCO) "Scenario" class.
The problem disappeared when using a context.CreateObject<Scenario> to create the (POCO) object i.s.o. a .... = new Scenario().
Faced the same issue today and used Value Injecter to solve it. It's as simple as:
var dynamicProxyMember = _repository.FindOne<Member>(m=>m.Id = 1);
var member = new Member().InjectFrom(dynamicProxyMember) as Member;
That's it :)