Trying to inject dependency into IIS hosted WCF service using MEF - c#

I'm trying to inject specific class into my WCF service but it doesn't work and I can't understand why. I'm VERY NEW to MEF and patterns, just trying to make it work. Watched series of videos to understand what it is about but bootstraping won't work in my case since it is not Silverlight
http://channel9.msdn.com/blogs/mtaulty/mef--silverlight-4-beta-part-1-introduction
Here is my Web application's Global.asax code. This is non MVC, just regular ASP.NET app:
private void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
var catalog = new WebScopedCatalog(new DirectoryCatalog(Server.MapPath("~\\bin")));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
FIRST, I'm not sure I even bootrstrap it properly.. SECOND, I'm using http://www.timjroberts.com/2011/02/web-scoped-mef-parts/ as a guidance for web-scoped parts. I need that because some injected objects supposed to live during request only.
Now, I have following class:
[Export(typeof(ITest))]
[WebPartCreationPolicy(WebCreationPolicy.Session)]
public class Test : ITest
{
public string TestMe()
{
return "Hello!";
}
}
And my service looks like:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MobileService
{
[Import]
public ITest MyTestClass { get; set; }
public MobileService()
{
int i = 10;
}
When breakpoint hits at i=10 - I have NULL inside MyTestClass. Clearly, MEF does not initialize this class for me. Am I missing something?
EDIT:
When I examine catalog - I see my class Exported but I don't see it imported anywhere...
EDIT 2:
Daniel, Thank you. It makes sense. It still feels litle like a magic for me at this point. Yes, WCF creates this service. Than I have MembershipProvider and various Utility classes that ALL need the same import. And I'm not creating neither of those classes so I can't have Mef creating them. (Service created by WCF, MembershipProvider created by who-knows-what, Utility classes have static methods..) I wanted to use Mef instead of storing my stuff in HttpContext.Current. My container object doesn't have SatisfyImports. It has SatisfyImportsOnce. What if I do it in many different constructors? Will Mef share same singleton or it will be creating new instance every time?
At this point I wonder if I should even use Mef in this particular scenario..

MEF won't satisfy imports for objects it doesn't create. What is it that creates MobileService? If it's not MEF, then the import won't be satisfied by default. Even if it is MEF, the import wouldn't be satisfied in the constructor- you can't set properties on an object you create until it is done being created (ie the constructor has finished).
You can call container.SatisfyImportsOnce(mobileService) to satisfy the imports of a part. You should try to avoid doing this everywhere you need a MEF import. If you can, you should export a part and import it from another part so that MEF handles the creation for you. However, it looks like this part may be created by WCF so you can't have MEF create it, and in that case it would be OK to use SatisfyImportsOnce.
Response to EDIT2: If you use the same container each time, MEF will by default only create one instance of the part with the export. You can set the CreationPolicy to NonShared (in either the export or import attribute) to change this.
As for whether it makes sense to use MEF the way you are trying to, I don't know enough about writing web services to give you any advice on that.

The web-scoped part creation policy that I wrote won't help with WCF services.
I've posted a new blog post that documents an approach to composeable WCF services:
http://www.timjroberts.com/2011/08/wcf-services-with-mef/
Basically, you need to implement a custom Instance Provider that is MEF-aware and can compose the WCF service object when it is created.

I wrote about how to compose your WCF in a generic way that its configuration based here:
Unit Testing, WCF and MEF
I actually built my solution on the code samples Tim Robert's provided in his post. only that I took it a bit further and instead of using code in the global asax i moved the configuration into the web.config so its easier to maintain.

Related

What does "FreshIOC.Container.Register" do?

I am doing a course of MVVM for Xamarin Forms, and the teacher in one class used FreshIOC.Container.Register to "register different instances or dependencies", and I don't understand how that affects my code, if someone can explain it I would appreciate it.
My code as an example:
public App()
{
InitializeComponent();
FreshIOC.Container.Register<IContactService,ContactService>();
FreshIOC.Container.Register<IUserDialogs>(UserDialogs.Instance);
}
class MainViewModel : FreshBasePageModel
{
private IContactService service;
private IUserDialogs dialog;
public MainViewModel(IContactService Service, IUserDialogs Dialog)
{
service = Service;
dialog = Dialog;
}
public override async void Init(object initData)
{
dialog.ShowLoading();
var tempt = await service.GetData();
Contacts = tempt;
dialog.HideLoading();
}
}
I don't see what FreshIOC.Container.Register does, or how it connects to the MainViewModel class. By the way, there is another method called "Resolve" instead of "Register", If you could also explain that one I would appreciate it.
That is all, if you need anything more from my code I will provide it as soon as I see your request, thank you all so much for your time, have a nice day.
The Register registers your concrete classes at the IoC framework.
So, IoC in short will work like this:
Instead of making new ContactService all the time, you'll ask the IoC framework to give you one.
This has some benifits;
because you often register by interface, you only need to worry about the ContractService constructor at one place, and not all over the place.
it makes your code better testable because the consuming page is not responsible for creating the service. This might sound a bit mystic, but if you write unit test, you'll immediate see the benefits.
what does Register do?
It makes sure you can request this service from the IoC framework.
The first one registers the ContactService as an IContactService; so, if you request an IContactService you'll get the registered type.
The second one registers the instance of a type: if you request it, you'll always get that instance. Works well for settings and thread safe stuff. Works not at all for database related things.
What does Resolve do?
It enables you to retrieve a service from the IoC framework, but note: there might be better ways e.g. by constructor injection.
This code is an example of constructor injection: by registering the IContactService you've enabled the possibility to resolve the service automatically. If you ommit the registration this is not possible:
public MainViewModel(IContactService Service, IUserDialogs Dialog)
{
service = Service;
dialog = Dialog;
}
If you didnt use the IoC framework, you would have ended up with new ContactService in every model you where using, which can be considered as an antipattern for such services, because;
changing the implementation concrete type will result in a lot of code changes.
changing the constructor would lead to a lot of code changes
unittesting the consumer causes an instantation of the service, which can lead to side effects.

How to instantiate outside of a constructor?

How to replicate this code with Autofac syntax?
public static class MenuConfig
{
public static void Initialize()
{
var _menuService = DependecyFactory.GetInstance<IMenuService>();
Parameters.Menu = _menuService.Menu();
}
}
Before calling this a "duplicate question" please note that I'm looking for an Autofac command. I CANNOT inject the interface anywhere and then call "Resolve". What I need to is perform an "InstancePerRequest" inline and uninjected so I don't have to do this:
var _service = new Service(new Dependency(new context()));
LightInject has a method that allows instantiation from an interface OUTSIDE of a constructor like this:
var _service = DependecyFactory.GetInstance<IService>();
What is the equivalent method for Autofac?
When calling containerBuilder.Build() you get back a container which implements IContainer and ILifetimeScope, whenever you get hold of one of these interfaces, you can resolve types from it:
container.Resolve<IService>();
If you want this container to be static, you could add the container as a static property to the Program or Startup class (depending if you're creating a Console or ASP.NET application).
Remember that the root container will be around for the entire duration of your application, so this can result in unwanted memory leaks when used incorrectly. Also see the warning in the documentation.
Still, it's perfectly possible to do the memory management yourself by resolving an Owned<> version from your interface:
using (var service = Program.Container.Resolve<Owned<IService>>())
{
service.Value.UseService();
}
Anyway, since you mention a static class in the comments, the best solution is to change that into a non-static class and register it as a singleton with Autofac. Then you can inject a Func<Owned<IService>> serviceFactory into that singleton and create/dispose an instance of the service wherever you need it.
using (var service = serviceFactory())
{
service.Value.UseService();
}
This is simply not possible with Autofac. All other solutions involving Autofac will require code refactoring which may potentially break software functionality. So unfortunately, the most elegant and least disruptive solution is this:
var _service = new Service(new Dependency(new context()));
Since this is an edge case addressing only one part of the software, this compromise is acceptable. It would be nice, however, if Autofac implemented this functionality in some future release.

Why do the clients create the repositories?

Please see the code below, which I took from Jimmy Bogards Wicked domain models:
public class OfferAssignmentService
{
private readonly IMemberRepository _memberRepository;
private readonly IOfferTypeRepository _offerTypeRepository;
private readonly IOfferValueCalculator _offerValueCalculator;
private readonly IOfferRepository _offerRepository;
public OfferAssignmentService(
IMemberRepository memberRepository,
IOfferTypeRepository offerTypeRepository,
IOfferValueCalculator offerValueCalculator,
IOfferRepository offerRepository
)
{
_memberRepository = memberRepository;
_offerTypeRepository = offerTypeRepository;
_offerValueCalculator = offerValueCalculator;
_offerRepository = offerRepository;
}
public void AssignOffer(Guid memberId, Guid offerTypeId)
{
// Retreive
var member = _memberRepository.GetById(memberId);
var offerType = _offerTypeRepository.GetById(offerTypeId);
// Delegate to business objects
var offer = member.AssignOffer(offerType, _offerValueCalculator);
// Save
_offerRepository.Save(offer);
}
}
Why are the repositories injected into the service? Say I have an app, which has four clients (mobile; WPF; MVC4; Win Forms), then all these clients have to create instances of these repositories and pass them to the service. Why does the service not just create them i.e. in one place.
I am obviously missing something here.
Update
If I create the repositories in the Serivce layer then their are four dependencies i.e. one for _memberRepository; one for _offerTypeRepository; one for _offerValueCalculator and one for _offerRepository. If I create all these instances in the four clients then I am creating 16 dependencies i.e. 4*4. I realise I am missing something fundamental here.
Your individual clients shouldn't be responsible for knowing how to configure these dependencies in detail. If your client depends on OfferAssignmentService then it shouldn't be responsible for knowing about all of the dependencies for that class, like the repositories, and the dependencies of those repositories, etc. If that code is duplicated wherever OfferAssignmentService is used then that can be improved.
Ideally there would be a single configuration class which serves as the composition root for this service layer, and that class would be referenced and used by clients to configure the dependencies for your service. The specifics vary depending on the container you're using. For example, with Windsor I would create a class that inherits from AbstractFacility. My client would simply do this:
container.AddFacility<OfferAssignmentServiceFacility>();
That facility would handle configuring all of the dependencies with my container.
In Unity it would be a class that inherits from UnityContainerExtension, and very similar to Windsor, you would do
container.AddNewExtension<OfferAssignmentServiceExtension>();
What they have in common is that they pass the container to the configuration class, allowing that class to configure the container with the dependencies it needs.
If you don't mind your service being tightly coupled to a container framework you can put that code directly in your service library. I like to make my libraries container-agnostic (they don't need one particular brand of DI container to work.) So I'll put the facility or extension in a separate library.

Dependency Injection in MS Dynamics CRM

I am currently getting started with the extending of Microsoft Dynamics CRM using Plugins.
Is it possible to add Dependency injection to these plugins (for testing, loose coupling, etc. purposes)? Where can I register my IoC-container so that it's used over all the plugins of the same type?
We've been trying to unit test and apply dependency injection on our Dynamics CRM application. Unfortunately, as Microsoft support and consultants are confirmed, there is no supported way to do it. You may either transfer all of your plugin business logic to an another business class and apply dependency injection or stop thinking about it.
If you choose to fight back with Dynamics CRM, you need to define a static field on a plugin super class which will be your DI Container. As follows,
public abstract class SuperPlugin : IPlugin{
public void Execute(IServiceProvider serviceProvider){
// initialize a static container instance if not available
var containerWrapper = new ContainerWrapper{
Container = serviceProvider.GetService(typeof(IPluginExecutionContext)),
Resolver = //static resolver instance of dependency container
};
OnExecution(containerWrapper);
}
public abstract void OnExecution(IDependencyResolver resolver);
}
I really cannot understand why Microsoft doesn't simply let us register some components to the IServiceProvider implementation that they are using internally.
Ps. Since your SuperPlugin class is an IPlugin, you may forget to write the interface implementation on the sub class. But we encountered some bugs on Plugin Registration tool that is shipped with official Dynamics CRM SDK. So in case you may have the same problem you should also implement your plugins as follows,
public class MyPlugin : SuperPlugin, IPlugin{
public abstract void OnExecution(IDependencyResolver resolver){};
}
Edit: See a small example that explains the concept https://github.com/nakahparis/DIForCRM
Plugins in CRM are the Bane of Unit Testing:
Issues with non-plugin test
No way to temporarily disable
Easy to forget it is running
Issues with testing plugins themselves
Unable to unit test and attach to process
A lot to mock out, Pipeline, Service Provider etc
Runs multi-threaded
This has led me to the following solution for testing plugins:
Get rid of the plugin context as quickly as possible, extracting out all objects and service required from it right away.
Create an ExecutePlugin method to hook unit tests into, and immediately call this method after extracting the objects from the plugin context.
Push as much code as possible into the business layer.
This results in plugins that look like this (with a heavy use of extension methods to make this simpler):
public void Execute(IServiceProvider provider)
{
var context = provider.GetContext();
var service = provider.GetService(context);
var target = GetTarget<Contact>(context);
if (target == null || !target.ContainsAllNonNull(c => new
{
c.FirstName,
c.LastName,
}))
{
// Entity is of the wrong type, or doesn't contain all of the required attributes
return;
}
ExecutePlugin(service, target);
}
public void ExecutePlugin(IOrganizationService service, Contact target){
// Logic Goes Here
}
Once this is done, the only thing you need to unit test the ExceutePlugin is your own IOrganizationService that mocks out the required calls and you have your unit testing done. I don't even bother unit testing the Execute method. Either it'll work, or it won't and blow chow on the first use from within CRM.

SignalR multiple hubs on different paths in same application?

I have an application which contains multiple hubs all on unique paths, so when calling the default :
routes.MapHubs("path", new HubConfiguration(...));
It blows up saying that the signalr.hubs is already defined (as mentioned here MapHubs not needed in SignalR 1.01?).
Now I can understand that it should only be called once, but then you will only get 1 path, so is there any way to handle a path per hub scenario? like how with MVC you specify the controller and action? so something like:
routes.MapHub<SomeHub>("path", new HubConfiguration(...));
== Edit for more info ==
It is mentioned often that you should never need to call this map hubs more than once, and in most scenarios I can agree, however I would not say that this is going to be the case for all applications.
In this scenario it is a website which at runtime loads any plugins which are available, each plugin is exposed the dependency injection framework to include its dependencies and the route table to include its routes. The hubs may have nothing to do with each other (other than the fact that they are both hub objects). So the hubs are not all known up front and are only known after the plugins are loaded, and yes I could wait until after this and try binding the hubs there, however then how do I have custom routes for each one then?
This seems to be a case of SignalR trying to abstract a little too much, as I dont see it being a bad idea to have custom routes rather than the default "/signalr", and as the routes all have different responsibilities it seems bad to have one entry route for them all.
So anyway I think the question still stands, as I dont see this as being a bad use case or bad design it just seems to be that I want to be able to have a route with a hub applied to it, much like in mvc you apply a controller and action to a route.
You shouldn't need more than the signalr.hubs route. If you point your browser to that route, you will see it automatically finds all public types assignable to IHub and creates a JavaScript proxy for them. You can interact with different hubs by name from JavaScript, i.e. if you have the following Hub:
public class GameHub : Hub
You can connect to that specific hub by doing:
var gameHubProxy = $.connection.gameHub;
You can also explicitly specify a name for your hub by adding the HubNameAttribute to the class:
[HubName("AwesomeHub")]
public class GameHub : Hub
You can then retrieve the specific proxy by doing
var awesomeHubProxy = $.connection.awesomeHub;
UPDATE:
I'm not sure whether SignalR will be able to run on multiple paths in the same application. It could potentially mess things up and the default assembly locator won't be able to pick up hubs loaded at runtime anyway.
However, there is a solution where you can implement your own IAssemblyLocator that will pick up hubs from your plugin assemblies:
public class PluginAssemblyLocator : DefaultAssemblyLocator
{
private readonly IEnumerable<Assembly> _pluginAssemblies;
public PluginAssemblyLocator(IEnumerable<Assembly> pluginAssemblies)
{
_pluginAssemblies = pluginAssemblies;
}
public override IList<Assembly> GetAssemblies()
{
return base.GetAssemblies().Union(_pluginAssemblies).ToList();
}
}
After you've loaded your plugins, you should call MapHubs and register an override of SignalRs IAssemblyLocator service:
protected void Application_Start(object sender, EventArgs e)
{
// Load plugins and let them specify their own routes (but not for hubs).
var pluginAssemblies = LoadPlugins(RouteTable.Routes);
RouteTable.Routes.MapHubs();
GlobalHost.DependencyResolver.Register(typeof(IAssemblyLocator), () => new PluginAssemblyLocator(pluginAssemblies));
}
NOTE: Register the IAssemblyLocator AFTER you've called MapHubs because it will also override it.
Now, there are issues with this approach. If you're using the static JavaScript proxy, it won't be re-generated every time it's accessed. This means that if your /signalr/hubs proxy is accessed before all plugins/hubs has been loaded, they won't be picked up. You can get around this by either making sure that all hubs are loaded by the time you map the route or by not using the static proxy at all.
This solution still requires you to get a reference to your plugin assemblies, I hope that's feasible...

Categories