Finding duplicate export in MEF - prism

I am using MEF and have a duplicate export in my composition container. When I do the following I can see the duplicate.
var exports = GlobalContainer.GetExports<IEventAggregator>();
But when I try to search the Parts of the composition container I cannot find the duplicate.
var parts = this.AggregateCatalog.Parts;
var definitions = new List<ExportDefinition>();
foreach ( var part in parts )
{
definitions.AddRange( part.ExportDefinitions );
}
definitions.Sort( ( a , b ) => string.Compare( a.ContractName , b.ContractName ) );
var extraDefs = new List<ExportDefinition>();
foreach ( var def in definitions )
{
if ( def.ContractName.Contains( "EventAggregator" ) )
extraDefs.Add( def );
}
I am using Prism and I need the EventAggregator prior to initialization of Prism. I can add the EventAggregator manually to the container as a CompositionBatch but after Prism is initialized I get an InvalidOperationException because there are two event aggregators. Is there a way to remove the export definition or a way to keep prism from loading its definition. In Prism 4 the MefEventAggregator is done as an export using the AssemblyCatalog so suppressing Prism creation might not be possible. I wanted to view the GetExports source code of the container but could not find it.

I assume you're using the Prism.MefExtensions library and have a MefBootstrapper. That library exports the EventAggregator for you in this source file
I can't think of a situation where you'd need the EventAggregator before the bootstrapper is run. Would it be enough to be able to access it there? The MefBootstrapper has the protected Container property that you can use to access the container and get the EventAggregator out.
Container.GetExportedValue<IEventAggregator>();
I suppose your other option would be to have your export definition as EventAggregator and stay away from the interface to avoid the duplicate.

Related

Override lazy loading on anonymous type with LINQ to entity

I have three entities generated by Entity Framework. One is event and this contains navigation properties called frogs and user_bookings. I posted a related question before about performing a sub-query which seems to work but it prevents me overriding lazy loading of a property.
var evts = from evt in context.events.Include("frogs")
where evt.event_id < 10
select evt;
This works - the navigation property frogs gets loaded.
However, when I alter the LINQ to this:
var evts = from evt in context.events.Include("frogs")
where evt.event_id < 10
select new
{
Event = evt,
HasBooked = evt.user_bookings.Any(x => x.user_id == 1)
};
I get an error trying to access the frogs because the ObjectContext no longer exists. I tried removing virtual from the class definition for the event class, but this just results in an empty list of frogs, when they are definitely there!
This is by design. Include is ignored when the query result is a projection, even when the projection contains an entity that could contain the Included properties.
I don't know why EF implemented it this way. If the projection doesn't contain any entities, but is just some type (anonymous or not), there is no Include target, so ignoring it makes sense. But if the projection does contain an Include target (Event in your case) it seems to me that they could have decided to make that work. But, well, they didn't.
Maybe it's because the rules when Include actually has an effect are less obvious than you might expect. In your case, the shape of the query changes after the Include, so it's ignored.
You could work around this by also querying the frogs:
from evt in context.events.Include("frogs")
where evt.event_id < 10
select new
{
Event = evt,
Frogs = evt.frogs,
HasBooked = evt.user_bookings.Any(x => x.user_id == 1)
};
Now each Event will also have its frogs collection filled (because of relationship fixup). But there are two gotchas. The collections are not marked as loaded, so -
if lazy load can occur afterwards, it will occur, making the initial load useless.
if lazy loading can't occur any more (because the context is disposed) you will get an exception.
This means that to make this work you have to disable lazy loading.

AJAX in Flux: Refreshing stores when dependent state changes

I'm building a Flux app using MartyJS (which is pretty close to "vanilla" Flux and uses the same underlying dispatcher). It contains stores with an inherent dependency relationship. For example, a UserStore tracks the current user, and an InstanceStore tracks instances of data owned by the current user. Instance data is fetched from an API asynchronously.
The question is what to do to the state of the InstanceStore when the user changes.
I've come to believe (e.g. reading answers by #fisherwebdev on SO) that it's most appropriate to make AJAX requests in the action creator function, and to have an AJAX "success" result in an action that in turn causes stores to change.
So, to fetch the user (i.e. log in), I'm making an AJAX call in the action creator function, and when it resolves, I'm dispatching a RECEIVE_USER action with the user as a payload. The UserStore listens to this and updates its state accordingly.
However, I also need to re-fetch all the data in the InstanceStore if the user is changed.
Option 1: I can listen to RECEIVE_USER in the InstanceStore, and if it is a new user, trigger an AJAX request, which in turn creates another action, which in turn causes the InstanceStore to update. The problem with this is that it feels like cascading actions, although technically it's async so the dispatcher will probably allow it.
Option 2: Another way would be for InstanceStore to listen to change events emitted by UserStore and do the request-action dance then, but this feels wrong too.
Option 3: A third way would be for the action creator to orchestrate the two AJAX calls and dispatch the two actions separately. However, now the action creator has to know a lot about how the stores relate to one another.
One of the answers in Where should ajax request be made in Flux app? makes me think option 1 is the right one, but the Flux docs also imply that stores triggering actions is not good.
Something like option 3 seems like the cleanest solution to me, followed by option 1. My reasoning:
Option 2 deviates from the expected way of handling dependencies between stores (waitfor), and you'd have to check after each change event to figure out which ones are relevant and which ones can be ignored, or start using multiple event types; it could get pretty messy.
I think option 1 is viable; as Bill Fisher remarked in the post you linked, it's OK for API calls to be made from within stores provided that the resulting data is handled by calling new Actions. But OK doesn't necessarily mean ideal, and you'd probably achieve better separation of concerns and reduce cascading if you can collect all your API calls and action initiation in one place (i.e. ActionCreators). And that would be consistent with option 3.
However, now the action creator has to know a lot about how the stores
relate to one another.
As I see it, the action creator doesn't need to know anything about what the stores are doing. It just needs to log in a user and then get the data associated with the user. Whether this is done through one API call or two, these are logically very closely coupled and make sense within the scope of one action creator. Once the user is logged in and the data is obtained, you could fire two actions (e.g. LOGGED_IN, GOT_USER_DATA) or even just one action that contains all the data needed for both. Either way, the actions are just echoing what the API calls did, and it's up to the stores to decide what to do with it.
I'd suggest using a single action to update both stores, because this seems like a perfect use case for waitfor: when one action triggers a handler in both stores, you can instruct InstanceStore to wait for UserStore's handler to finish before InstanceStore's handler executes. It would look something like this:
UserStore.dispatchToken = AppDispatcher.register(function(payload) {
switch (payload.actionType) {
case Constants.GOT_USER_DATA:
...(handle UserStore response)...
break;
...
}
});
...
InstanceStore.dispatchToken = AppDispatcher.register(function(payload) {
switch (payload.actionType) {
case Constants.GOT_USER_DATA:
AppDispatcher.waitFor([UserStore.dispatchToken]);
...(handle InstanceStore response)...
break;
...
}
});
Option 1 seems the best choice conceptually to me. There are 2 separate API calls, so you have 2 sets of events.
It's a lot of events in a small amount of code, but Flux relies always using the simple, standard Action->Store->View approach. Once you do something clever (like option 2), you've changed that. If other devs can no longer safely assume that any Action flow works the exact same as every other one, you've lost a big benefit of Flux.
It won't be the shortest approach in code though. MartyJS looks like it will be a little neater than Facebook's own Flux library at least!
A different option; if logins must always refresh the InstanceStore, why not have the login API call include all of the InstanceStore data as well?
(And taking it further; why have 2 separate stores? They seem very strongly coupled either way, and there's no reason you couldn't still make calls to the InstanceStore API without re-calling login anyway)
I usually use promises to resolve such situation.
For example:
// UserAction.js
var Marty = require( 'marty' );
var Constants = require( '../constants/UserConstants' );
var vow = require( 'vow' );
module.exports = Marty.createActionCreators({
...
handleFormEvent: function ( path, e ) {
var dfd = vow.defer();
var prom = dfd.promise();
this.dispatch( Constants.CHANGE_USER, dfd, prom );
}
});
// UserStore.js
var Marty = require( 'marty' );
var Constants = require( '../constants/UserConstants' );
module.exports = Marty.createStore({
id: 'UserStore',
handlers: {
changeUser : UserConstants.CHANGE_USER
},
changeUser: function ( dfd, __ ) {
$.ajax( /* fetch new user */ )
.then(function ( resp ) {
/* do what you need */
dfd.resolve( resp );
});
}
});
// InstanceStore.js
var Marty = require( 'marty' );
var UserConstants = require( '../constants/UserConstants' );
module.exports = Marty.createStore({
id: 'InstanceStore',
handlers: {
changeInstanceByUser : UserConstants.CHANGE_USER
},
changeInstanceByUser: function ( __, prom ) {
prom.then(function ( userData ) {
/* OK, user now is switched */
$.ajax( /* fetch new instance */ )
.then(function ( resp ) { ... });
}
});

Are ElasticClient.MapRaw and .CreateIndexRaw gone?

After updating to NEST 0.11.5, it appears as if the NEST.ElasticClient.MapRaw and .CreateIndexRaw methods aren't supported anymore. Have they been renamed or moved or are they completely gone?
In case they're gone, how can I define custom analysis settings on index creation? This is what I've tried:
var indexSettings = new IndexSettings()
{
NumberOfReplicas = 1,
NumberOfShards = 2,
Analysis = new AnalysisSettings() // doesn't work, no setter
{
// here's where my settings would go...
}
};
var response = elasticClient.CreateIndex(indexName, indexSettings);
Doesn't work since there's no setter defined for IndexSettings.Analysis.
The Raw calls have been pushed down to elasticClient.Raw.CreateIndexPost(...).
For the 0.11.5.0 release i created my own script that scans the elasticsearch source code to generate all the raw calls. Appearantly the elasticsearch dev's have also done this so the IRawElasticClient signatures might changes again in the 0.11.6.0 release as NEST will be compatible with the new low level client guidelines.
Also be sure to check out the MapFluent() call though
https://github.com/Mpdreamz/NEST/blob/master/src/Nest.Tests.Unit/Core/Map/FluentMappingFullExampleTests.cs
And CreateIndex() also exposes a fully mapped fluent variant
https://github.com/Mpdreamz/NEST/blob/master/src/Nest.Tests.Integration/Indices/Analysis/Analyzers/AnalyzerTests.cs#L19

how to create a new record in form datasource from x++

In form Journal Voucher (AR>Journal> PaymentJournal> clicking buttonLines). I want to create a new record from x++ code.
I have seen few methods in the form viz create(), initvalue(), ledgerJournalEngine_custPayment... etc which are called when we press ctrl+n . How we could use these methods through x++ code to create a record using standard functionality.
plz help.
Before you elaborated, I thought you were trying to create your own custom form extending the journal functionality. If you're just trying to create a tool, you can just create a new Settlement Using Cust Group button. In the clicked event, call your transaction marking form or whatever you do to get the transactions you want to use. Then put something like this in it:
void clicked()
{
;
element.lock();
super();
// Put your code here to call the open transaction editing code
// CREATE THIS CUSTOM METHOD on C\LedgerJournalEngine_CustPayment\settleTransCustGroup
ledgerJournalEngine.settleTransCustGroup(ledgerJournalTable);
ledgerJournalTrans_ds.active();
ledgerJournalTrans_ds.reread();
ledgerJournalTrans_ds.executeQuery();
//recalculate balances
ledgerJournalEngine.newJournalActive(ledgerJournalTable, true);
element.firstField();
element.unLock();
}
Then in the new method you created, which I named settleTransCustGroup, you can loop over your records in the testLedgerJournalSpecTrans modeling off of something similar to this (custom method created on the engine class):
void settleTransCustGroup(LedgerJournalTable _ledgerJournalTable)
{
LedgerJournalTrans ledgerJournalTrans;
;
// Turn this stuff into a loop and default whatever else you need
ledgerJournalTrans.clear();
ledgerJournalTrans.initValue();
ledgerJournalTrans.AccountNum = '100003';
ledgerJournalTrans.AmountCurCredit = 10;
this.initValue(ledgerJournalTrans);
ledgerJournalTrans.insert();
this.write(ledgerJournalTrans);
ledgerJournalTrans.clear();
ledgerJournalTrans.initValue();
ledgerJournalTrans.AccountNum = '100005';
ledgerJournalTrans.AmountCurCredit = 15;
this.initValue(ledgerJournalTrans);
ledgerJournalTrans.insert();
this.write(ledgerJournalTrans);
}
Generally, your X++ code would look something like this:
static void InsertRecord(Args _args)
{
LedgerJournalTrans ledgerJournalTrans;
;
ledgerJournalTrans.AccountNum = "10000";
ledgerJournalTrans.AmountCurCredit = 50.64;
ledgerJournalTrans.AccountType = LedgerJournalACType::Ledger;
ledgerJournalTrans.insert();
}
You can replace the fields and values as needed. If any fields are missing, the error will display in the infolog (for example, if you were to run the above, you will get a "Currency code must be specified" error), so be sure all required fields are addressed.
In most cases, you can also call ledgerJournalTrans.initValue(); before assigning your values to pre-populate the record with default AX values. I believe this will be the same as what you see when you use Ctrl + N on the form. In the above example, doing so will cause the Currency Code to be filled in, and the record to be saved correctly (at least on our system).
There is no magical way of calling standard funcionality out of the frameworks quoted here on other comments. For each Ledger Type (Accounting, Inventory, Orders, Payments, ...), the way of creating and initializing lines is different and you have to work on this specific way if you want the journal to post properly.
There are a lot of examples on google of X++ code that inserts journal transactions for almost every type of them. It's not easy, but at least it's always almost the same code and it can be easilly reused.

Is it possible to use existing classes as POCOs in Entity Framework

I was able to generate pocos using POCO template from Microsoft. It works great.
My question is how I could modify this or any other template to use existing objects from a different assembly, and just load data into them.
The way i tried going about it, was to create POCO's using the template, and the PocoGenerator.Context to use existing Model, and than modify generated code to return my clasess instead of its generated classes.
this gives me the dreaded "Mapping and metadata information could not be found for EntityType MyType".. This may be because there are a few extra fields in database that my object's don't have. I tried modifying entity objects and removing those fields but that cause some other problems..
has anyone done this?
UDPATE
yep, existing classes can be used. The one thing to watch out for, is the un-informative error above will be triggered if there is a mismatch between some property names, or types. Occasionally the runtime will give a meaningful error with name of property that is incompatible, but that's only if both classes are really close.
Anyways, to use existing classes as pocos, simply generate the pocos, and than comment out the generated classes. Than in xxxPocoGenerator.Context.cs add necessary namespace of your existing objects to be used.
As a side note, i wrote the following code to compare my existing classes, with POCO generated ones and show any that do not match so i could fix them.
var properties = typeof(MyExistingClass).GetProperties();
var tproperties = typeof(MyPOCOClass).GetProperties();
Console.WriteLine("---------------------------------Missing or Different Properties--------------------");
List<PropertyInfo> missingOrDifferentProperties = new List<PropertyInfo>();
foreach (var tp in tproperties)
if (properties.Where(p => p.Name == tp.Name && p.PropertyType == tp.PropertyType && p.CanRead == tp.CanRead && p.CanWrite == tp.CanWrite && p.IsSpecialName == tp.IsSpecialName && p.MemberType == tp.MemberType).Count() != 1)
Console.WriteLine(tp.Name + " :: " + tp.PropertyType.Name);
Sounds like you may be looking for Code-First which is in the latest CTP4 for Entity Framework.
See Link
as requested, here is my resolution as answer:
UDPATE
yep, existing classes can be used. The one thing to watch out for, is the un-informative error above will be triggered if there is a mismatch between some property names, or types. Occasionally the runtime will give a meaningful error with name of property that is incompatible, but that's only if both classes are really close.
Anyways, to use existing classes as pocos, simply generate the pocos, and than comment out the generated classes. Than in xxxPocoGenerator.Context.cs add necessary namespace of your existing objects to be used.
As a side note, i wrote the following code to compare my existing classes, with POCO generated ones and show any that do not match so i could fix them.
var properties = typeof(MyExistingClass).GetProperties();
var tproperties = typeof(MyPOCOClass).GetProperties();
Console.WriteLine("---------------------------------Missing or Different Properties--------------------");
List<PropertyInfo> missingOrDifferentProperties = new List<PropertyInfo>();
foreach (var tp in tproperties)
if (properties.Where(p => p.Name == tp.Name && p.PropertyType == tp.PropertyType && p.CanRead == tp.CanRead && p.CanWrite == tp.CanWrite && p.IsSpecialName == tp.IsSpecialName && p.MemberType == tp.MemberType).Count() != 1)
Console.WriteLine(tp.Name + " :: " + tp.PropertyType.Name);

Resources