Need help converting PRISM Unity Module Init to PRISM MEF Module Init - prism

I need help converting the following class for use in a program that I am developing. The original was a demo program from IdeaBlade called "PRISM EXPLORER" based on Unity. I need help converting one part from UNITY to MEF. I handled everything else. Just stuck on this one. I already marked my classes with the MEF "[EXPORT(typeof(XXX))]" and I think I need to use the "ComposeExportedValue" somehow. The confusing part is finding the equivelant for this line:
var provider =
(IEntityManagerProvider) _container.Resolve<IPersistenceGateway>();
_container.RegisterInstance<IEntityManagerProvider>(provider);
THANKS!
The following is the entire class I need to convert. You can find the original here: Ideablade PRISM Page
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.Regions;
using Microsoft.Practices.Unity;
using PrismExplorer.Infrastructure;
namespace ModelExplorer.Explorer {
public class ExplorerModule : IModule {
private readonly IUnityContainer _container;
public ExplorerModule(IUnityContainer container) {
_container = container;
}
public void Initialize() {
InitializeContainer();
SetViews();
}
// ToDo: Consider getting from configuration
private void InitializeContainer() {
RegisterGatewayAndEntityManagerProvider();
_container.RegisterType<IQueryRepository, QueryRepository>(
new ContainerControlledLifetimeManager()); // singleton
}
private void RegisterGatewayAndEntityManagerProvider() {
_container.RegisterType<IPersistenceGateway, PrismExplorerPersistenceGateway>(
new ContainerControlledLifetimeManager()); // singleton
var provider =
(IEntityManagerProvider) _container.Resolve<IPersistenceGateway>();
_container.RegisterInstance<IEntityManagerProvider>(provider);
}
private void SetViews() {
var regionManager = _container.Resolve<IRegionManager>();
var view = _container.Resolve<ExplorerView>();
regionManager.AddToRegion(RegionNames.MainRegion, view);
regionManager.RegisterViewWithRegion(RegionNames.MainRegion, typeof(ExplorerView));
}
// Destructor strictly to demonstrate when module is GC'd
//~MevModule() {
// System.Console.WriteLine("Goodbye, MevModule");
//}
}
}

The two corresponding methods on a CompositionContainer are ComposeExportedValue<T>(...), which allows you to add a specific instance to the container, and GetExportedValue<T>(...) which gets an instance of T from the container.
If you can design your types in a way to reduce this use of service location and try and prefer constructor injection, it will make your code much easier to maintain and test. E.g., could your code be transformed into:
[Export(typeof(IModule))]
public class ExplorerModule : IModule
{
[ImportingConstructor]
public ExplorerModule(IPersistenceGateway gateway)
{
}
}

Related

Unity interface mapping exception in web api

I am getting this exception while debugging code:
Resolution of the dependency failed, type = "Aqueduct.Interfaces.IMasterDataClient", name = "MDS".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type,
Aqueduct.Interfaces.IMasterDataClient, is an interface and cannot be constructed. Are you missing a type mapping?
At the time of the exception, the container code was:
Resolving Aqueduct.Interfaces.IMasterDataClient,MDS
Unity.config:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
IUnityContainer myContainer = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
myContainer.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
myContainer.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Web Api controller:
using (var container = new UnityContainer())
{
container.Resolve<IMasterDataClient>("MDS");
container.Resolve<ILinksManager>("LDS");
}
MasterDataClient Interface Implementing class:
public class MasterDataClient : HalClient, IMasterDataClient, IHalClient, ICrestaClient
{
public MasterDataClient(IApiClient apiClient, IUriDispenser dispenser);
}
You have three problems here.
Problem 1. You're creating a new container:
using (var container = new UnityContainer())
{
container.Resolve<IMasterDataClient>("MDS");
container.Resolve<ILinksManager>("LDS");
}
This container will be empty and have 0 registrations. It's not the same container as you made your registrations to. There's a couple of ways to solve it:
Problem 1 - Solution 1: Don't inject the container. Inject the dependencies.
Instead of using the container you should inject your dependencies directly to your controller:
public class MyApiController : ApiController
{
IMasterDataClient _masterDataClient;
ILinksManager _linksManager
public MyApiController(IMasterDataClient masterDataClient, ILinksManager linksManager)
{
_masterDataClient = masterDataClient;
_linksManagerlinksManager;
}
}
This way you can avoid the service locator-pattern and your dependency to the container itself. If you're using named registrations you may need to use the Dependency-attribute.
With Unity how do I inject a named dependency into a constructor?
Problem 1 - Solution 2: Inject your container instead of creating a new one.
If you really need your controller for some reason, then you should try to inject it instead. This way you will get the same container as you used for your registrations.
public class MyApiController : ApiController
{
IUnityContainer _container;
public MyApiController(IUnityContainer container)
{
_container = container;
}
}
Problem 1 - Solution 3: Keep an static reference to your container.
As a last resort you can keep your container as a static instance.
public static class IocContainer
{
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
return container;
});
public static IUnityContainer Instance
{
get { return Container.Value; }
}
}
And in your registrations:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = IocContainer.Instance;
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
myContainer.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
myContainer.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Usage:
IocContainer.Instance.Resolve<IMasterDataClient>("MDS");
Problem 2. You don't seem to register the dependencies for MasterDataClient.
It has dependencies for IApiClient and IUriDispenser. They need to be registered as well.
Problem 3. You assign your dependency resolver to the wrong container
You currently create two containers - myContainer and container. You make your registrations to one container, and then use another one as DependencyResolver. You can solve it by removing myContainer and only use container. Otherwise you will not be able to use your registrations in Web Api.
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
container.RegisterType<ILinksManager, LinksManager>("LDS");
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
Update:
I don't know implementing classes for IApiClient and IUriDispenser as
it is third party dll so how can I register it
Unity needs to know which implementation to use when you resolve an interface. So somehow you need to tell Unity what implementation to use. There's an excellent answer from Mark Seemann in the question below:
Unity IoC for resolving assemblies dynamically
It scans the assembly for implementations of your interface and then registers them/it.
Alternatively you can use registration by convention, which enables you to do several registrations at once:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMapping.MatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
Note that this will register all implementations, including your own.
If you just want the third party implementations you should be able do do something like this:
// Get the assemblies where IApiClient exists.
IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => x.GetTypes().Contains(typeof (IApiClient)));
// Register all implementations based on convention.
container.RegisterTypes(AllClasses.FromAssemblies(assemblies),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled); // Maybe another lifetime manager?
Update 2:
Make sure that the controller has a parameterless public constructor.
The error above can have many causes, most of them are covered in these questions:
Unable to inject DBContext into my Web API 2 Controller with Unity
Make sure that the controller has a parameterless public constructor error
error: Make sure that the controller has a parameterless public constructor webapi
Mostly it's Unity telling you that you're trying to resolve something that you didn't register. Or that you haven't registered a DependencyResolver at all.

load repository with constructor parameters in Web API (1)

I'm trying to get the following scenario using autofac but I'm not sure how my code will be built to get this up & running.
I have a repository class, this repository class needs to get a project key (string) on initialization (constructor). I want to instantiate this repository in initialization of my "Initialize" method provided to my by Web Api, because the project key will be available in my route.
so instead of calling "new ProductRepository(projectKey)", I want to use Autofac. Can someone point me in the right direction? I didn't find any way to send in specific data to the container in web api, since the container/builder is only available in the appStart.
Should I make the container available as a singleton so that I can approach it, or is this bad practice?
in your initialization code:
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
in your controller:
public class MyController : ApiController
{
public MyController(IComponentContext container)
{
var key = new NamedParameter("projectKey", "keyFromRoute");
var repository = container.Resolve<ProductRepository>(key);
}
}
That should do it.
There is a nuget package that provides a DependencyResolver for WebApi that integrates with AutoFac. Create the DependencyResolver, assign it to the config, register your controllers in the autofac container.
I'm making some assumptions because you didn't provide your code, but I think you have something like this:
public class ProductRepository
{
public ProductRepository(DbContext dbContext, int projectKey)
{
}
}
public class SomeController : Controller
{
private readonly Func<int, ProductRepository> _repoFactory;
public SomeController(Func<int, ProductRepository> repoFactory)
{
_repoFactory = repoFactory;
}
public void DoStuff(int projectKey)
{
var repo = _repoFactory(projectKey);
repo.DoStuff();
}
}
public class RepositoryModule : Module
{
public override Load(ContainerBuilder builder)
{
builder.RegisterType<ProductRepository>();
}
}

RavenDB with Ninject in ASP.NET MVC3

I want to use RavenDB with ninject in my asp.net mvc3 project, Any idea how I have to configure this?
kernel.Bind<Raven.Client.IDocumentSession>()
.To<Raven.Client.Document.DocumentStore>()
.InSingletonScope()
.WithConstructorArgument("ConnectionString", ConfigurationManager.ConnectionStrings["RavenDB"].ConnectionString);
Here's how I do mine:
If you install Ninject with Nuget, you'll get an /App_start/ NinjectMVC3.cs file. In there:
private static void RegisterServices(IKernel kernel)
{
kernel.Load<RavenModule>();
}
Here's the RavenModule class:
public class RavenModule : NinjectModule
{
public override void Load()
{
Bind<IDocumentStore>()
.ToMethod(InitDocStore)
.InSingletonScope();
Bind<IDocumentSession>()
.ToMethod(c => c.Kernel.Get<IDocumentStore>().OpenSession())
.InRequestScope();
}
private IDocumentStore InitDocStore(IContext context)
{
DocumentStore ds = new DocumentStore { ConnectionStringName = "Raven" };
RavenProfiler.InitializeFor(ds);
// also good to setup the glimpse plugin here
ds.Initialize();
RavenIndexes.CreateIndexes(ds);
return ds;
}
}
And for completeness here's my index creation class:
public static class RavenIndexes
{
public static void CreateIndexes(IDocumentStore docStore)
{
IndexCreation.CreateIndexes(typeof(RavenIndexes).Assembly, docStore);
}
public class SearchIndex : AbstractMultiMapIndexCreationTask<SearchIndex.Result>
{
// implementation omitted
}
}
I hope this helps!
I recommend using a custom Ninject Provider to set up your RavenDB DocumentStore. First place this in your code block that registers your Ninject services.
kernel.Bind<IDocumentStore>().ToProvider<RavenDocumentStoreProvider>().InSingletonScope();
Next, add this class that implements the Ninject Provider.
public class RavenDocumentStoreProvider : Provider<IDocumentStore>
{
var store = new DocumentStore { ConnectionName = "RavenDB" };
store.Conventions.IdentityPartsSeparator = "-"; // Nice for using IDs in routing
store.Initialize();
return store;
}
The IDocumentStore needs to be a singleton, but do not make the IDocumentSession a singleton. I recommend that you simply create a new IDocumentSession using OpenSession() on the IDocumentStore instance Ninject gives you whenever you need to interact with RavenDB. IDocumentSession objects are very lightweight, follow the unit-of-work pattern, are not thread-safe, and are meant to be used and quickly disposed where needed.
As others have done, you might also consider implementing a base MVC controller that overrides the OnActionExecuting and OnActionExecuted methods to open a session and save changes, respectively.

Accessing ninject kernel in Application_Start

I am using Ninject and the MVC3 extension installed with nuget. My kernel setup code is in the App_Start/NinjectMVC3.cs file. Everything works great in controllers, but I can't figure out how to (properly) bind interfaces in the Global.asax.cs MvcApplication code.
I ended up using a hack (creating a public NinjectMVC3.GetKernel() method that returns bootstrap.kernel). However, that will be deprecated, and there must be a proper way to do this that I am not seeing.
Here is my code:
public class LogFilterAttribute : ActionFilterAttribute
{
private IReportingService ReportingService { get; set; }
public LogFilterAttribute( IReportingService reportingService )
{
this.ReportingService = reportingService;
}
...
}
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters( GlobalFilterCollection filters )
{
filters.Add( new HandleErrorAttribute() );
filters.Add( new LogFilterAttribute() );
}
...
protected void Application_Start()
{
...
RegisterGlobalFilters( GlobalFilters.Filters );
// NOTE hack:
var kernel = NinjectMVC3.GetKernel();
var logger = kernel.Get<ILogger>();
var bw = new BackgroundWork(logger);
Application["BackgroundWork"] = bw;
bw.Start();
}
}
There are two interfaces I am interested in. The first is just binding an object to a Global variable (the ILogger for the BackgroundWork).
And the second is for an ActionFilter. I read http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/, but I don't see how it plugs into the actual registration (filter.Add).
I don't want to use the Property Inject if I can avoid it.
Any thoughts on the proper way to do this?
Thanks
MVC 3 introduces the DependencyResolver which is populated into a singleton, and the Ninject extension supports it. You could use that in your MvcApplication class if you need it:
protected void Application_Start()
{
// ...
var logger = DependencyResolver.Current.GetService<ILogger>();
}
Now I should point out that it is unnecessary to do this with action filters. In Ninject.MVC3 you are supposed to use the BindFilter syntax, like so:
// Declare empty attribute
public class MyFilterAttribute : FilterAttribute { }
// Dependency module
public class MyModule : NinjectModule
{
public override void Load()
{
// Other bindings
// ...
this.BindFilter<MyActionFilter>(FilterScope.Action, 1)
.WhenControllerHas<MyFilterAttribute>();
}
}
Note that you have to use this because BindFilter is an extension method, and you also have to reference the Ninject.Web.Mvc.FilterBindingSyntax namespace.

Create class that implements a particular design pattern with ReSharper

Design patters are a point of arguments between developers, but I use them very often. Even more, I use one of the most controversial of all common patterns - singleton.
Here is how I implement it in C#:
class MySingletonClass
{
private static volatile MySingletonClass _instance;
private static object syncRoot = new Object();
public static MySingletonClass Instance
{
get
{
if (_instance == null)
{
lock (syncRoot)
{
if (_instance == null)
_instance = new MySingletonClass();
}
}
return _instance;
}
}
private MySingletonClass()
{
}
}
I want to be able to automatically create singleton classes while developing, with only entering a name for the class.
How can I implement this functionality with ReSharper? Can ReSharper pattern catalog be used for this?
Thank you.
You can create a Code Template for it (a File Template if you wish every singleton in a new file).
There are instructions on how to create a template from scratch and from existing code in the help files.

Resources