I faced with strange problem. My app has next code, that execute on startup:
protected override void RegisterTypes()
{
// App.container - UnityContainer
var dvcc = new MyClientCore(new MySorter());
App.container.RegisterInstance(typeof(ClientCore), dvcc);
App.container.RegisterInstance(typeof(MyClientCore), dvcc);
this.dataProvider = new MyProvider();
this.dataProvider.Configure(App.container);
App.container.RegisterInstance(typeof(Provider), this.dataProvider);
App.container.RegisterInstance(typeof(MyProvider), this.dataProvider);
// Create view models and register them in container
this.RegisterViewModels();
// Command - singleton, that resolved in ctor view models,
// that registered in RegisterViewModels();
Command.Instance.InitCommands();
// Create and configure shell
}
When app execute in debug configuration there are no problem. Also when app execute in release configuration in visual studio.
But when I try to start app directly I get TypeInitializationException in Command ctor because of resolution of the dependency registered in dataProvider.Configure method.
I thought that cause in JIT optimization, and code may be execute like
protected override void RegisterTypes()
{
Command.Instance.InitCommands();
// other method body
}
I found solution for that - mark RegisterTypes method atribute [MethodImpl(MethodImplOptions.NoOptimization)].
But maybe exist better method to fix it? Also I will be gratiful for link, when that situation explained with simple words.
P.S. Sorry for my english.
Related
I am working with a WPF based application and using Autofac to resolve the dependency of DbContext of Entityframework. I used the below code to register my data module.
public class DataModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<DataContext>()
.As<IDbContext>()
.WithParameter("nameOrConnectionString", "DefaultConnectionString")
.InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
}
}
This works fine while using in normal scenario but while using TPL, due to simultaneous calls to repository, it creates error stating that "ExecuteReader requires an open and available Connection. The connection's current state is open."
In web application, this can be resolved using InstancePerRequest to resolve dependency per request but in WPF I need to resolve this dependency per Thread request. Is there any way out for this?
I have review InstancePerRequest summary or autofac and it states that this method is used for Web request only:
// Summary:
// Share one instance of the component within the context of a single web/HTTP/API
// request. Only available for integration that supports per-request dependencies
// (e.g., MVC, Web API, web forms, etc.).
Update:
This is a simple async method that I used to get the data:
private async void OnLoadClientDetail()
{
long clientId = SelectedClient != null ? SelectedClient.Id : 0;
var listOfCollection = await _collectionService.GetCollectedCollectionAsync(clientId);
CollectionList = new ObservableCollection<CollectedCollection>(listOfCollection);
}
Here OnLoadClientDetail is bound to selection change event of a combobox. When user change the selection frequently then this method will be called multiple times. The _collectionService is injected in the viewmodel and has InstancePerLifetimeScope define. So how can I get different scope for all this calls?
As far as I can see, you share the _collectionService instance across the different event handlers by injecting it by Constructor Injection.
It probably better to use Method Injection here, so you'll get the instance per call, as you need, resolving it before method:
builder.Register(c =>
{
var result = new MyObjectType();
var dep = c.Resolve<TheDependency>();
result.SetTheDependency(dep);
return result;
});
I'm using Nancy with TinyIoC to solve the dependencies.
One dependency in particular needs to be application-lifecycle singleton.
If I do it with a default constructor it works:
container.Register<IFoo, Foo>().AsSingleton(); // WORKS
but if i try this with some arguments on the contructor it does not:
container.Register<IFoo>((c, e) => new Foo("value", c.Resolve<ILogger>())).AsSingleton();
// FAILS with error "Cannot convert current registration of Nancy.TinyIoc.TinyIoCContainer+DelegateFactory to singleton"
Whithout .AsSingleton(), it works again, but I don't get a singleton:
container.Register<IFoo>((c, e) => new Foo("value", c.Resolve<ILogger>()));
// Works, but Foo is not singleton
Any Ideas? I think the mistake should be obvious but I can't find it.
I've used up all my google-foo.
EDIT
The code runs here:
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
// here
}
}
What you're doing there is telling TinyIOC "every time you want one of these, call my delegate", so if you want to use that method you have to handle the singleton aspect yourself.
Unless you particularly need the deferred creation it's easier to do:
container.Register<IFoo>(new Foo("value", c.Resolve<ILogger>()));
That will then always use that instance whenever you want an IFoo.
The WPF application uses Caliburn.Micro as MVVM framework. CM has it's built in IoC-Container named SimpleContainer, I replaced it with Castle.Windsor container. (But container type does not matter here I guess.) CM uses a Bootstrapper.Configure() method where container can be configured. After that Bootstrapper.OnStartup() method starts application displaying a View for root ViewModel. So container configures before first View appears. In my case container configuration a pretty complex and may cause errors. For example I want to deserialize some XML files from app directory to objects and register them as components in container. So I want to get a SplashScreen to see container configuring progress, and then if all OK, splash disappears, container resolves root item and application starts as expected. If not - problem shown on splashscreen. I can't get in mind how to get a SplashScreenView (binded to SplashScreenViewModel) before I get a configured container. So application divides on "before" and "after" container. How can that issue can be solved? Is there any patterns? Is it OK to partly configure container in Configure and partly somewhere else, after it Resolved some components? Or maybe there is a practic to use container instance "inside" components resolved by another container instance? Thanks.
public class CastleModernUIBootstrapper : BootstrapperBase
{
private WindsorContainer _container;
public CastleModernUIBootstrapper()
{
Initialize();
}
protected override void Configure()
{
_container = new WindsorContainer();
// here components are registered.
// I want perform complex container configuration here,
// but I can't vizualize what happens here.
_container.Register(Component.For<LoadingSplashScreenViewModel>());
// ...
}
// ...
protected override void OnStartup(object sender, StartupEventArgs e)
{
// after we resolving first element from container
DisplayRootViewFor<LoadingSplashScreenViewModel>();
}
}
WPF has a built-in (as in I don't know how it works) Splash Screen. Just use "Add new item" on your project. It does work with Caliburn.
It's only a simple bitmap, but it takes care of the appearance. You can handle your errors as normal data.
You don't want your Splash window to be the Root View anyway.
I am working with Caliburn.Micro v2.0.1 on a Windows 8.1 Unversal (WinRT) project.
I followed the Caliburn.Micro Working with WinRT example.
My code looks as follows:
App.xaml.cs
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
Initialize();
DisplayRootViewFor<LoginViewModel>();
}
protected override void PrepareViewFirst(Frame rootFrame)
{
_container.RegisterNavigationService(rootFrame);
}
LoginViewModel.cs
public LoginViewModel(INavigationService navigationService, ...)
{
...
}
The issue
The OnLaunched is called first.
Initialize() Configures the WinRT container.
The DisplayRootViewFor<LoginViewModel> invokes an instance of the LoginViewModel and results in a Null exception because NavigationService has not yet been registered by PrepareViewFirst(Frame)
PrepareViewFirst(Frame) is not yet called, having a dependency on the RootFrame that should be configured by OnLaunched
Thus LoginViewModel is dependent on RegisterNavigationService and RegisterNavigationService is dependent on DisplayRootViewFor<LoginViewModel>() which is dependent on LoginViewModel
Is there any way to overcome this circular reference issue?
Register your services in the container before resolving the Views - this way all dependencies are available in the particular Dependency Injection container and you can use ServiceLocator to find them.
Typically I've always done this in the OnStartup() method of App.xaml.cs.
You should register/configure your container at the composition root, the earliest access point of your application.
This point depends on what kind of Application you have:
ASP.NET MVC: Global.asax.cs
Console Application: the Main Method
WPF: Application.OnStartup
WinPhone 7: See https://stackoverflow.com/a/7310492/455493
etc.
Check the Windows 7 lifecycle on http://msdn.microsoft.com/en-us/magazine/hh148153.aspx
Apparently, this method no longer gets called... In there we have code for configuring AutoMapper, and for setting model binders.
I know there is a "new" way to do model binders, but... shouldn't I still be able to do it "the old way" until I get that implemented?
Specifically, I have two lines left from my old Application_Start() method that I have been unable to get working:
AutoMapperConfiguration.Configure();
ModelBinders.Binders[typeof (ModuleEditModel)] = new DerivedModelBinder();
I've tried simply popping those into the constructor, right after the call to: ServiceLocatorManager.SetLocatorProvider(() => new StructureMapServiceLocator());
And that runs, but.. it seems somehow not to take effect. In running the application it is clear that AutoMapper isn't happy, doesn't have the mappings it is supposed to have, etc.
I answered this question out on the Turbine Discussion board on CodePlex. Here's the source for making the changes you ask for:
public class MvcApplication : TurbineApplication {
static MvcApplication() {
// Register the IoC that you want Mvc Turbine to use!
// Everything else is wired automatically
// For now, let's use the Unity IoC
ServiceLocatorManager.SetLocatorProvider(() => new UnityServiceLocator());
}
public override void Startup(){
// Gets called when the application starts up
// and before all the stuff that Turbine wires up
}
public override void Shutdown() {
// Gets called when the application shuts down
// and before any cleanup is done by Turbine
}
}
Hope this helps!