Ninject - How to dynamically select an implementation to bind to an interface - ninject

I'm currently using Ninject to create instances of interfaces in a WCF Services application.
Bind<IObjA>().To<ObjA>().InRequestScope();
Bind<IObjB>().To<ObjB>().InRequestScope();
Bind<IObjC>().To<ObjC>().InRequestScope();
It works great, but we are going to have several implementations of IObjC. What options do I have for continuing fluid assignment of implementation to interface for IObjA/IObjB but allowing for configurable assignment for IObjC?
I found a related question on SO but I don't know if I can support both a fluid and a configurable approach simultaneously.
For example, can I use Ninject.extensions.xml for IObjC while continuing to use the above approach for IObjA and IObjB?
Is it advisable to have conditional assignment for IObjC? That seems dirty but at the same time appears very simple.
if (condition1)
Bind<IObjC>().To<ObjC1>().InRequestScope();
else if (condition 2)
Bind<IObjC>().To<ObjC2>().InRequestScope();
Also, I know other frameworks like Castle support XML configuration but I would like to continue using Ninject.

1 - your bindings to IObjC have nothing to do with any other bindings. it doesn't matter where, when, or how you bind other services.
2 - you can use the XML extensions, but I would ask why you think you need it to be configurable.
3 - there are 2 possibilities for your conditional. first is that you want to make a decision at startup to determine whether to use ObjC1 for the entire lifetime of the app, or ObjC2. if that's the case, your code is ok. however, if you want to dynamically decided which object to use each time you resolve the binding, you will need to put the condition inside your binding, like so:
Bind<IObjC>().ToMethod( ctx => condition ? ctx.Kernel.Get<ObjC1>() : ctx.Kernel.Get<ObjC2>() );
alternately, you can use Named bindings:
Bind<ILog>().ToConstant( LogManager.GetLogger( "Accounting" ) ).Named( "Accounting" );
or "When" conditions to help:
Bind<ILog>().ToConstant( LogManager.GetLogger( "Background" ) ).When( context => context.Target != null && context.Target.Name == "backgroundLogger" );

Related

Override lazy loading behavior 'lazy=false'

I would like to override the default lazy loading behavior which is set in mappings as 'lazy=false'. Can't change it as many parts of existing application depend on this setting.
After spent some hours on it I didn't find a solution so I'm asking here.
How to do this?
What I want to achieve is to fine tune my query to load only what is needed.
This is what I've tried already:
Using QueryOver api:
var properties = session.QueryOver<Property>()
.Fetch(prop => prop.Transactions).Eager
.Fetch(prop => prop.Districts).Eager
//I dont want to load those entities below so I mark
//them as lazy - IT DOESN'T WORK
//I can see in SQL that they are getting loaded in separate queries
.Fetch(prop => prop.Districts.First().Aliases).Lazy
.Fetch(prop => prop.Districts.First().PolygonPoints).Lazy
.Skip(i * pageSize)
.Take(pageSize)
.List();
Using Criteria api:
var criteria = session.CreateCriteria<Property>();
criteria.SetFetchMode("Transactions", NHibernate.FetchMode.Join);
criteria.SetFetchMode("Districts", NHibernate.FetchMode.Join);
criteria.SetFetchMode("Districts.Aliases", NHibernate.FetchMode.Select); // tried Lazy too
criteria.SetFetchMode("Districts.PolygonPoints", NHibernate.FetchMode.Select); // tried Lazy too
criteria.AddOrder(NHibernate.Criterion.Order.Asc("Id"));
criteria.SetFirstResult(i * pageSize);
criteria.SetMaxResults(pageSize);
var properties = criteria.List<Property>();
Using any of the above methods 'Aliases' and 'PolygonPoints' are always being loaded when calling List<>(). I don't need them in my process.
I'm using Nhibernate 4.0.
Any ideas?
We cannot override mapping in this case. We can do it opposite way - have lazy in place - and use eager fetching for querying.
The decision process (of reference loading) is done outside of the query, ex post. So it could be pre-loaded, but cannot be avoided.
Solution here could be of two types.
The first is preferred (by me) - do your best and make laziness the default: Ayende -
NHibernate is lazy, just live with it
Use projections. Instruct NHibernate to create just one query, use transformer to get expected object graph - without any proxies in it
There is pretty clear example how to (properly) use projection list even for references:
Fluent NHibernate - ProjectionList - ICriteria is returning null values
And we would also need Custom result transformer, which will ex-post create all the references from the returned data:
Custom DeepResultTransfomer

zend acl dynamic assertions : when/how to load the resource?

i'm creating a zend framework 2 application and i'm sort of trying to implement what is explained here:
http://ralphschindler.com/2009/08/13/dynamic-assertions-for-zend_acl-in-zf
The demonstration that the code works is really nice, but it doesn't really apply to how a framework (utilizing mvc) works. Or maybe i'm just on the wrong track...
i've created a RouteListener like this :
class RouteListener implements ListenerAggregateInterface
{
public function attach(EventManagerInterface $events)
{
$this->listeners[] = $result = $events->attach(
MvcEvent::EVENT_DISPATCH, array($this, "checkAcl"), 100
);
}
}
the method checkAcl then checks if you're allowed to do what you want to do.
The resource and action are determined like this:
$resource = $routeMatch->getParam("controller");
$action = $routeMatch->getParam("action");
And the role is determined by the identity stored in the session (which implements Zend\Permissions\Acl\Role\RoleInterface)
Following the example: how do i determine if a user is allowed to edit a certain blog-post?
By the time acl is doing it's checking, the controller hasn't loaded the blogpost yet, so i'm not sure how to approach this. Unless i duplicate the retrieval of the blogpost in the assertion, but that i'm hoping there is a better way.
I'm also using doctrine for my persistence layer and in the end i've solved this problem using doctrine's Lifecycle Events. This allows you to trigger the acl-check whenever you want: when a entity (p.e. a blog-post) is loaded, or saved, etc.

ContentHandler issues (circular reference) in Orchard

crosspost: https://orchard.codeplex.com/discussions/459007
First question I have is what would be the repercussions of having 2 PartHandlers for the same Part in 2 different modules?
I got into this predicament because I have to run a method once a specific Content Type is created. It would be as easy to hook onto OnCreated for the part, however, here is my scenario:
Module A contains the part and the original handler
Module B contains the service where the method is
Module B has a reference to Module A
Therefore, I am unable to reference Module B within Module A (circular reference). So what I did was to copy the exact same PartHandler in Module A and placed it in Module B.
Would anything be wrong with that?
Then comes my second question, which I think could solve all these problems: Can we create a PartHandler for the Content Item's default Content Part? (i.e. the part where all custom fields are attached to)
This would definately make things easier as I could consolidate stuff that need to run there.
UPDATE 1 (to better explain question 2)
ContentDefinitionManager.AlterPartDefinition("EventItem",
builder => builder
.WithField("StartDate", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("Start Date")
.WithSetting("DateTimeFieldSettings.Display", "DateOnly")
.WithSetting("DateTimeFieldSettings.Required", "true"))
.WithField("StartTime", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("Start Time")
.WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
.WithField("EndDate", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("End Date")
.WithSetting("DateTimeFieldSettings.Display", "DateOnly"))
.WithField("EndTime", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("End Time")
.WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
.WithField("Intro", cfg => cfg
.OfType("TextField")
.WithDisplayName("Intro")
.WithSetting("TextFieldSettings.Flavor", "textarea"))
ContentDefinitionManager.AlterTypeDefinition(
"EventItem"
, cfg =>
cfg
.DisplayedAs("Event Item")
.WithPart("TitlePart")
.WithPart("EventItem")
.WithPart("LocationPart")
.WithPart("AutoroutePart", builder => builder
.WithSetting("AutorouteSettings.AllowCustomPattern", "true")
.WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false")
.WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Title', Pattern: 'learn/events/{Content.Slug}', Description: 'learn/events/event-title'}]")
.WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
.WithPart("CommonPart")
.Draftable()
.Creatable()
);
I'm talking about creating a ContentHandler for the EventItem part which holds all the custom fields. How can I go about it when EventItemPart is not defined in any class in the solution?
The following below won't work since it can't find the class EventItemPart:
OnCreated<EventItemPart>((context, keynotes) =>
questionService.SetDefaultQuestions(context.ContentItem));
Cross-answer as well.
Bertrand's perfectly right. Why do you need to reference B in A in first place? If the service from B needs A and A needs this service, then it belongs to A (at least the interface - contract).
You can always split interface and actual implementation for your service, having one in different module than another. If implementation of your service requires stuff from B, then put the interface in A, but actual implementation in B. This way A doesn't even need to know about the existence of B, but still be able to use the service via it's interface - it's the beauty of IoC pattern and Orchard modularity:)
You may use ContentPart or IContent as a type argument in handler generic methods. It's perfectly valid. This way you'd be able to plug in to events on all items, and perform custom filtering afterwards (based on type name, some field existence etc.). In your case it may look like:
OnCreated<ContentPart>((context, part) =>
{
if(part.ContentItem.ContentType != "EventItem") return;
questionService.SetDefaultQuestions(context.ContentItem);
});
Update: no need to do this: .WithPart("EventItem"). This 'fake' part will be automatically added by framework.
Cross-answer:
none
However, repeating yourself is almost always wrong, especially if it's done for a bad reason. Why is are the service and the part in two different modules? Why does A need B? A circular reference indicates tight coupling. If the tight coupling is justified, then it should happen in a single module. If it's not, then you need to re-do your design to remove it.
You can create a handler for anything, but your explanation of your scenario is way to vague and abstract to give any useful advice.

FlexNativeMenu with robotlegs

I an using the Robotlegs framework and I am busy with an AIR desktop application and I want to use FlexNativeMenu. THe problem is that I am not able to create a view class based on mx.controls.FlexNativeMenu for dependency injection. When not using Robotlegs the code is pretty straightforward - any help will be appreciated. Thanks.
generally you can use whatever you want to a view. The problem is that the mediator's onRegister method will be called only if your view dispatches ADDED_TO_STAGE event. And because FlexNativeMenu doesn't fire this event your mediator is not working (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/FlexNativeMenu.html#eventSummary)
for RobotLegs v2
If you're trying to inject into the FlexNativeMenu (hereinafter referred to FNM), you can try something like this (I'd do this in your IConfig implementor):
injector.injectInto( fnmInstance );
If you are trying to inject an instance of FNM (say in it's mediator):
[Inject]
public var view:MyFNMClass;
If you are trying to attach a mediator to the FNM instance you do something like this in your IConfig implementor:
//requires that you map the FNM (assuming you're subclassing it)
mediatorMap.map( MyFNMClass ).toMediator( MyFNMClassMediator );
//else where where you decide to wire it up
mediatorMap.mediate( fnmInstance );
The "gotcha" is this: There isn't a very pretty way to access the FNM prior to injection. I grabbed it like so:
//very nasty I know
var fnm:MyFlexNativeMenu = FlexGlobals.topLevelApplication.myMenu;
code
Made a git repo - https://github.com/jusopi/RobotLegs-v2-FlexNativeMenu-example

Named singleton instance in StructureMap (Multiple nHibernate session factories)

I have a scenario where I have two Nhibernate SessionFactorys I need to register an use with StructureMap. Only Foo needs mySessionFactory sessions.
Like this:
For<ISessionFactory>().Singleton().Use(NHibernateConfiguration.GetDefaultSessionFactory());
For<ISession>().HybridHttpOrThreadLocalScoped().Use(x => x.GetInstance<ISessionFactory>().OpenSession());
For<ISessionFactory>().Singleton().Use(AnotherNHibernateConfiguration.GetDefaultSessionFactory).Named("mySessionFactory");
For<ISession>().HybridHttpOrThreadLocalScoped().Use(x => x.GetInstance<ISessionFactory>("mySessionFactory").OpenSession()).Named("mySession");
For<Foo>()
.Use<Foo>()
.Ctor<ISession>("session").Is(x => x.TheInstanceNamed("mySession"));
The problem is that mySessionFactory is now used everywhere when I only wanted to to be used in Foo and everywhere else should use my unnamed instance.
What I'm I doing wrong?
On both your named instances, change Use to Add. Use sets that instance as the default as well as adding it as an instance. You could also reverse the order of your config (the last instance of a type added with Use will become the default), but using the Add method is much more explicit.