Unity 2 is behaving strangely with generics - c#

I am right now having big trouble with Unity 2 in my MVC 3 project.
I have created an abstract BaseViewPage that all viewpages inherits from. In this i have 2 dependencies. So far so good.
Now i have 3 different Viewpages that inherit from the BaseViewPage. These uses generics to deliver some specific data to the view. So far so good.
Now comes the problem.
In my homecontroller i use unity to resolve one of those viewpages. The viewpage gets loaded correctly when i debug it but right after my call to return view("index", model); unity makes a call to one of those dependencies inside the baseviewpage. This is done when the httpcontext is null.
Unity config (Loads all the viewpages):
container.RegisterType<IBackendWrapper, BackendWrapper.BackendWrapper>(new PerThreadLifetimeManager());
container.RegisterType<BaseViewPage, EmptyViewPage>("EmptyViewPage");
container.RegisterType(typeof(BaseViewPage), typeof(GenericViewPage<>), "GenericViewPage");
container.RegisterType(typeof(BaseViewPage), typeof(GenericIEnumerableViewPage<>), "GenericIEnumerableViewPage");
BaseViewPage and one generic view page (the other generic pages looks almost the same):
public abstract class BaseViewPage
{
[Dependency]
public IBackendWrapper Backend { get; set; }
....
}
public class GenericViewPage<T> : BaseViewPage
{
public T Model { get; set; }
public GenericViewPage(T model)
: base()
{
Model = model;
}
}
Now in my home controller i have first a dependency to Backend (to test that it works), then inside the Index i use unity to resolve one generic view page:
public class HomeController : Controller
{
[Dependency]
public IBackendWrapper Backend { get; set; }
public ActionResult Index(MvcLoginUser user)
{
var model = UnityGlobalContainer.Container.Resolve<GenericViewPage<MvcLoginUser>>("GenericViewPage");
return View("Index", model);
}
}
Now after the return, unity makes a call to the BackendWrapper object. More precisely BackendWrapper.UserIdent.TheLogin. TheLogin throws an error since there is no HttpContext present. Question is, why does unity try to access it? I have implemented a dispose inside the BackendWrapper and inside the UserIdent but unity ignores them and still calls TheLogin.
Inside the BackendWrapper i have a constructor that calls an external dll to create a new UserIdent. So its nothing that Unity is resolving. But unity still tries to access it.
Also, if i remove the dependency from the BaseViewPage it works perfectly. So only when BaseViewPage has a dependency to BackendWrapper is this problem occurring.
Did i configure it correctly?

I found out that this "Application_EndRequest" was hit BEFORE unity has cleaned up its objects. This in turn terminated our NHibernate session, so when unity then tried to dispose of all objects inside the created classes it would fail. Still have not figured out why it tries to dispose of non created classes. The wrapperclass was created by unity and the wrapper class in turn created the UserIdent. My guess is that the garbage collector or something ran and tried to go through all the created classes and their child objects. This was done outside the HttpContext which resulted in several exceptions.

Related

Passing object of class defined in assembly1 to assembly2, without changing assembly1

I am trying to create tools for a game to learn, as well as improve my own playing experience.
The primary .NET assembly, csass.dll, that controls the client is heavily obfuscated, and I have no control over this .dll-file at all and reading it's code is very time consuming. The game also includes a mainapi.dll which handles the communication between server and client. I have full control over this assembly and I can listen to the servers responses and send my own requests, which already gives me some pretty nice functionality, however there are some limitations I'd like to work around.
csass.dll references mainapi.dll, by default mainapi does not reference csass. In csass.dll there is a class, let's call it clickHandler, that has a public, non-static method ClickObj() of return type void. I want to call this method from within mainapi.dll, but I have no idea how to go about this, given that I have to leave csass.dll untouched.
Are there any feasible ways to 'retrieve' a clickHandler object (to then call its ClickObj() method) from within the mainapi assembly, without making any changes in csass.dll? Appreciate any and all input!
Create an interface:
public interface IClickHandler
{
void ClickObject();
}
Now create a helper class implementing that interface:
using CsAss;
public class ObjectClicker : IClickHandler
{
CsAss _csass;
public ObjectClicker(CsAss csass)
{
_csass = csass;
}
public void ClickObject()
{
_csass.clickObject();
}
}
Add a dependency on an instance of the interface into your MainAPI class:
public class MainApi
{
IClickHandler _clickHandler;
public MainApi(IClickHandler clickHandler)
{
_clickHandler = clickHandler;
// Now you have a class that can call the click handler for you
}
}
Now wire it all up:
public void StartupMethod()
{
var csass = new CsAss();
IClickHandler clickHandler = new ObjectClicker(csass);
var main = new MainApi(clickHandler);
// TODO: Start your app now that MainApi is properly configured
}
That last step is the only potentially tricky part, depending on your project layout. You need something that can create an instance of CsAss, MainApi and ObjectClicker. Normally I would solve that with the dependency injection (DI) pattern, either using a framework such as Autofac or so-called "poor man's DI" by manually instantiating from a central startup method. That gets a little more difficult with Unity since there isn't an easily accessible startup point. You could start looking into https://github.com/svermeulen/Zenject and go from there for options.

creating a class like App.xaml.cs in Class Library Project

So recently; I refactored Views to their own WPF Application project and I moved my ViewModel classes into their own Class Library project. This worked well for keeping my code in order. Then I realised that I didn't have the comfort of the App.xaml.cs class.
This class (for me) meant that I could declare all sorts of objects and access them application wide.
i.e: In the App.xaml.cs
public partial class App : Application
{
public myDatabaseEntities context { get; set; }
// App.xaml.cs Constructor
public App()
{
context = new myDatabaseEntities();
}
}
In some random View Model:
myDatabaseEntities context = ((App)Application.Current).context;
The above allows me to recylce the instance, and comes in particularly handy with Unity's (IoC container) version of lifetime manager.
Thing is, I'm not sure on how to achieve this behaviour within a class Library project. I'm not sure how to create a class that instantiates at runtime. And I have no clue how to pass that App class instance around to relevant classes. Any ideas on how to do this? Any help would be much appreciated.
Personally, I would keep all the "functionally" related Views and ViewModels together (next to each other). You may want to create class libraries (or modules) based for different functional parts of the application. Also, please refer to this MSDN page on building composite application using WPF and Prism.
Coming to your question, have an interface called IApplication defined something like this:
public interface IApplication
{
MyDatabaseEntities Context { get; }
}
and implement that interface on App class:
public partial class App : Application, IApplication
{
public MyDatabaseEntities Context { get; set; }
// App.xaml.cs Constructor
public App()
{
Context = new MyDatabaseEntities();
}
}
In your App.xaml.cs, as part of bootstrapping your application register this App instance with the container by calling RegisterInstance extension method on Unity container:
Container.RegisterInstance(typeof (IApplication), this, new ContainerControlledLifetimeManager());
Now, if your ViewModels take a dependency on IApplication, then they will have access to your App object and to the Context property via this interface. In future you could expose additional properties like: Dispatcher, Resources, etc from your App object through this interface.
Turns out all I needed was a regular class without the xaml front end. Then inherit the Application class. And lastly set it as the base class for app.xaml.cs. The answer is already here

MEF and Caliburn.Micro ViewModelFactory with Parameters

I've been working with Caliburn.Micro and MEF and I'm trying to get a viewmodelfactory implementation working. What I'm attempting is to create a chain of ViewModels for a dialog window (each ViewModel instantiates one or more viewmodels to generate the overall layout of the window). I'm having trouble importing the viewmodelfactory correctly; I can get it without a problem using [ImportingConstructor], however when I try to use [import] I end up with a null reference exception against viewModelFactory.
The "ViewModelFactory" which I have implemented is as per:
http://blog.pglazkov.com/2011/04/mvvm-with-mef-viewmodelfactory.html
and I'm trying to import the viewmodel as per the following:
[Import]
public IViewModelFactory viewModelFactory { get; set; }
and IViewModelFactory itself has an export declared (and works correctly with [ImportingConstructor]
[Export(typeof(IViewModelFactory))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ViewModelFactory : IViewModelFactory
Attempt 2
MY next effort was trying to add an instance of ViewModelFactory into the composition container:
protected override void Configure()
{
var catalog =
new AggregateCatalog(
AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());
container = new CompositionContainer(catalog);
var batch = new CompositionBatch();
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue<IViewModelFactory>(new ViewModelFactory());
batch.AddExportedValue(container);
container.Compose(batch);
}
However this results in an error within the ViewModelFactory, stating that the composition container which is Lazy loaded is null.
I'm trying to find a solution that will allow me to still use the Factory approach, as it allows me to use constructor parameters which are currently required as part of my viewmodels.
EDIT
I was able to get this to work by having an "Initialise" function within my viewmodels, using [ImportingConstructor] on my ViewModels with a constructor that only contains the IViewModelFactory declaration. However, this now required me to instantiate the viewmodel and make a call to the "initialise" function whenever I am creating these, so a more elegant approach would be great.
Thanks.
Managed to implement a different solution to this, which was to use:
IoC.Get<*ViewModelName*>();
Still haven't worked out why the [Import] by itself didn't work, however this certainly solved the issue for me.

Ninject Creating an Extra Instance when using NinjectHttpModule

For some reason Ninject is creating an additional instance of my object when I use NinjectHttpModule in my MVC 4 app.
If I use NinjectHttpModule (the Ninject.MVC3 default) but do not actually have any IHttpModule classes that require constructor injection, it works fine. But as soon as I create a class that implements IHttpModule and that requires constructor injection, Ninject for some reason creates two instances of my object.
I added some tracking code to the class that is being duplicated to verify that it was being duplicated. Every time an instance is created, the static count variable is incremented:
namespace Trigger.Events
{
public class TriggerEventRegistry : ITriggerRegistry
{
private static int count;
public TriggerEventRegistry()
{
TriggerEventRegistry.count++;
}
}
}
Here is my IHttpModule:
namespace TriggerDevelopment.ApplicationTriggers
{
public class RegisterTriggerComponentsHttpModule : IHttpModule
{
ITriggerEventRegistry eventRegistry;
public RegisterTriggerComponentsHttpModule(ITriggerEventRegistry eventRegistry)
{
this.eventRegistry = eventRegistry;
}
}
....
}
By the time a TriggerEventRegistry is injected into my controller (on the same request), the TriggerEventRegistry.count equals 2. If I comment out the constructor on RegisterTriggerComponentsHttpModule, then the value of TriggerEventRegistry.count equals 1 (which is should since there should only be one instance/request).
Here is the binding code:
Bind<ITriggerEventRegistry>().To<TriggerEventRegistry>().InRequestScope();
Any help on this would be greatly appreciated!
Note
I even made a request to my app using curl to avoid multiple HTTP requests being made by the browser looking for assets, a favicon or something like that. Still no joy.
Update
Upon further investigation, I'm also seeing that the ctor and the Init method of RegisterTriggerComponentsHttpModule is being called twice.
It's going to call your HttpModule as many times as there are requests. For instance, most web browsers submit at least two requests, the page request and a favicon request. Try adding something like an image to the page, and see if you get three requests...

Prism, Unity and default type registration in Modules

Technologies
C# 4.0
Prism 4 with Unity for DI
WPF
MVVM
Preface
There are two projects in my solution, MyApp.Shell and MyApp.ModuleFoo
MyApp.Shell's Unity Bootstrapper
protected override IModuleCatalog CreateModuleCatalog()
{
// Module assemblies are read from a directory.
DirectoryModuleCatalog moduleCatalog = new DirectoryModuleCatalog();
moduleCatalog.ModulePath = #".\Modules";
return moduleCatalog;
}
The project MyApp.ModuleFoo contains a View and a View Model.
The ViewModel
// Somehow, Unity sees this class and registers the type.
public class FooViewModel : ViewModelBaseClass
{
public string FooText
{
get { return "Foo!"; }
}
}
The View
<Label Content={Binding FooText} />
The View's Code-behind
// Unity automatically sees this as Constructor Injection,
// which is exactly what I desire.
public FooView(FooViewModel viewModel)
{
DataContext = viewModel;
...
}
MyApp.FooModule's Initialization
Perhaps registering FooView with the region manager is inadvertently registering FooViewModel with Unity?
public void Initialize()
{
var regionManager = ServiceLocator.Current.GetInstance<IRegionManager>();
regionManager.RegisterViewWithRegion("FooRegion", typeof(FooView));
}
The view correctly displays "Foo!".
Problems
How do I tell Unity to register only a single instance of FooViewModel?
Additionally, (and I'm thinking ahead here), how would I tell unity not to register FooViewModel?
Thanks for the help.
Edit:
Added MyApp.FooModule's Initialization code
Edit (Solution):
It turns out RegisterViewWithRegion has two overloads. From Prism's documentation, when the overload I'm using is used, a new instance of the view is created. I'm assuming this also creates a new instance of FooViewModel.
The other overload uses a delegate to resolve FooView. The documentation says this overload is used in the "ViewModel-first" approach. I'm going to make this question as answered, but if anyone has any additional insight, I'd love to hear.
// Somehow, Unity sees this class and registers the type.
public class FooViewModel : ViewModelBaseClass
...
I am surprised that you say this as Unity does not register types inside the container by default. You have to tell it to do so either programmatically or in the config file.
When you have concrete classes (not interfaces) they will automatically get created by Unity whether they are registered or not. If not the default behavior is to create a new instance each time. No lifetime management is applied also.
As far as your questions:
To register only one type within your initialisation of your module just have.
Container.RegisterType<FooViewModel>(new ContainerControlledLifetimeManager());
The lifetime manager will instruct unity to only create one instance of the view model.

Categories