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.
Related
We're using ASP.NET core and are running into the problem, that some registered services (from third-party libraries) request a specific 'service' (based on an interface) that has been deprecated.
The problem is that we don't know which libraries are using this deprecated service interface.
What we've done so far is:
create a custom implementation for the service interface
and registered this custom implementation (class) with DI
// Registration
services.AddTransient<IServiceInterface>((services) => new CustomCustomService(Log.Logger));
// Custom implementation
internal class CustomService : IServiceInterface
{
public CustomService (ILogger logger)
{
logger.Warning("!!! CustomService is still being used !!!");
}
}
So now we can see that the unwanted service is being used 'somewhere'.
But is it in some way possible to detect for which service the deprecated service has been created?
I've tried listing the stack trace using
var st = new System.Diagnostics.StackTrace();
logger.Warning("!!! CustomService is still being used !!!" + Environment.NewLine + "{stacktrace}", st.ToString());
But that doesn't seem to give information about the service using the deprecated service...
You can try the following:
var registrationsDependingOnMyService =
from descriptor in services
where descriptor.ImplementationType != null
let dependencies =
from ctor in descriptor.ImplementationType!.GetConstructors()
from param in ctor.GetParameters()
select param.ParameterType
where dependencies.Contains(typeof(IServiceInterface))
select descriptor;
This will query the IServiceCollection for registrations whose implementation type have a constructor argument of type IServiceInterface.
This might not be a bulletproof solution, as types or registrations can more sneakily depend on the service collection (e.g. by calling back into the IServiceProvider from within a registration delegate), but this is likely the best you can do with MS.DI.
So basically - as expected - it's not possible to exactly know which libraries (for which you don't have the code) use a certain dependency.
It's just trial and error ;)
Thanks for the ideas everyone.
So recently I started a project with Ardalis Clean Architecture as template it was all nice but when signalR came into my project i can't figure it. I'm trying to inject interface that my hub implements and call it's method, but everytime when it's called it throws NullReferenceException, it seems like all of the signalR components are null within this injected interface. Registered all hubs and registered it's interfaces using AutoFac. Trying to avoid situation when I'm forced to reference signalR package within core layer.
Core layer:
public class UpdateTimerNotificationHandler : INotificationHandler<UpdateTimerNotification>
{
private readonly ITimerHub _timerHub;
public UpdateTimerNotificationHandler(ITimerHub timerHub)
{
_timerHub = timerHub;
}
public Task Handle(UpdateTimerNotification notification, CancellationToken cancellationToken)
{
return _timerHub.UpdateTimerAsync(notification);
}
}
public interface ITimerHub
{
Task UpdateTimerAsync(UpdateTimerNotification updateTimerNotification);
}
Infrastructure layer:
public class TimerHub : Microsoft.AspNetCore.SignalR.Hub, ITimerHub
{
private readonly IAccountRepository _accountRepository;
public TimerHub(IAccountRepository accountRepository)
{
_accountRepository = accountRepository;
}
public Task UpdateTimerAsync(UpdateTimerNotification updateTimerNotification)
{
return Clients.All.SendAsync("UpdateTimer", updateTimerNotification);
}
}
private void RegisterHubs(ContainerBuilder builder)
{
foreach (var assembly in _assemblies)
{
builder.RegisterHubs(assembly);
}
builder.RegisterType<TimerHub>().As<ITimerHub>();
}
Web layer:
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
containerBuilder.RegisterModule(new DefaultCoreModule());
containerBuilder.RegisterModule(
new DefaultInfrastructureModule(builder.Environment.EnvironmentName == "Development"));
});
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
var app = builder.Build();
GlobalHost.DependencyResolver = new AutofacDependencyResolver(app.Services.GetAutofacRoot());
I was trying manually registering hubs with no luck, still same issue
The good news is SignalR already implements IHubContext<T> In your case you don't need to inject ITimerHub interface. If your TimerHub Already Implements ITimerHub that's good enough In your case it would look like this
public class HomeController : Controller
{
private readonly IHubContext<TimerHub> _hubContext;
public HomeController(IHubContext<TimerHub> hubContext)
{
_hubContext = hubContext;
}
}
Also you didn't show your startup.cs class.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSignalR();
...
}
and
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.MapHub<TimerHub>("/yourEndPointGoesHere");
}
If you really wanted to, which I don't recommend is [look at it here][1]
There is an example on using IHubContext in generic code.
I understand you're trying to learn something new. And yes, it's important to decouple application so you're headed in the right direction in what you want to achieve. However I wouldn't recommend this approach you are taking. His approach doesn't apply to 99% of the projects out there. Let me explain my point of view. Don't get pulled in by the buzz words in his videos and blogs. It's important to understand that these principals are SUBJECTIVE to your application.
You don't have 15,000 classes, services, views, and N Layers etc... in your app.
You don't need the flexibility of a domain driven approach. I've seen massive and I mean massive projects, ones that are 25 years old and have millions of lines of code. Let me tell you you're not swapping out your data layer all willy nilly like he makes it seem to be. On a big project there is no "it makes it easy" way to do that. Putting it in Repos and a data access layer doesn't really help. You can put in a data access layer, or in your services. You still need to test out 150,000 lines of code. The only time it's been useful for me is when I've had 4 data sources all having a getBy... function that needs to aggregate info from 4 sources. You don't need it for unit testing either. Just create a mock variable in your unit tests no need to mock your db connection. I find it more useful to have your unit tests actually hooked up to a database even though it's a dependency, it's actually useful.
He said it himself "You can go with a minimalist API and work your way up from there" Which is what you should do. What's the point of SOLID and Repos in a project with no code? For example the I in solid is implementation of interfaces. Interfaces do 2 things -
A. Tell your application what it should and shouldn't do. so, what are you enforcing that could break or needs this kind of abstraction?
B. Decouple the application. Where do you have 3+ different classes being injected in one piece of code with the same DoSomething() based on the type?
He touches over other things that only apply when you have 500 different things going on, and his case it's still overkill.
If you want to break it up you can take a simple approach.
-MainApiProject
-ServicesProject (you can also put interfaces in here)
-InterfacesProject(if you need them between multiple projects and have a lot of them)
-UtilitiesProject
Then look at what he's doing and if you see you need it take it.
I can go on but this is getting long as is.
[1]: https://learn.microsoft.com/en-us/aspnet/core/signalr/hubcontext?view=aspnetcore-6.0
Ive written a couple of unit tests while using dependency injection and the httpClient in the .net Core 2.0 framework.
Ive been testing my controllers like this:
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
But now i wanted to mock an object and after searching a bit on the internet all i could find was to do it like this:
var controller = new ProductionLineController(mockProductionLineProvider);
which is not testing the routing and on top of that i would have to create a lot of objects. so i dont want mock my object in this way.
I would like to be able to replace the service with an mock object i havent found a way to get the IServiceCollection into my unittest method.
I would like to be able to do something like this:
var mockingDate = new DateTime(date.Year, date.Month, date.Day, 12, 00, 00);
__constantsMock.Setup(x => x.GetCurrentDateTime()).Returns(mockingDate);
services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object));
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
I hope you can help me think of ways to get to a solution that doesnt involve me having to create every object that i would inject normaly.
Thank you in advance
edit:
im indeed doing integration tests, i want to test everything but i need to be able to configure the result coming from a DateTime.Now so i made the constants class with a function to return the datetime.now and im trying to mock/stub the class/function. that way i can test multiple scenario's that could occur.
You are looking at the standard way of mocking; you create stubs for all the dependencies (you need to be able to control all of them!) and create the controller. Being able to mock the DI framework wouldn't really buy you anything; you would still need to provide all the dependencies to the class when you constructed it.
Use mocking libraries like NSubstitute to make it easier; if you feel like you have too many dependencies then I would suspect you need to refactor your design (perhaps that controller does too much).
Note that testing with actual HTTP requests is more of an integration test; you are testing the whole app instead of just one class. In that case you can set up different environments for your program and have one that will set up the injector with whatever extra mocks/test data you need.
Once you start doing something like issuing a request to an action, you're pretty much well outside of unit test territory. What you're doing here is integration testing.
As long as you're doing integration testing, you might as well use TestServer, which will actually give you a much more accurate platform for integration tests. Setting up all the dependencies manually doesn't do anything for you in ensuring that your application actually functions as it should. The full documentation is here, but basically, you just do:
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>());
_client = _server.CreateClient();
The return of _server.CreateClient() is actually an instance of HttpClient, so your actual test code doesn't really need to change. However, now you've got a full mockup of all your services and config baked in.
The solution to my problem was as follows:
Make an extra starting class that inherits from your StartUp class
Give that class the following code:
public class UnitTestStartup : Startup
{
public static IServiceProvider ServiceProvider;
public static IServiceCollection Services;
public static Mock<IConstants> ConstantsMock;
public void ConfigureTestingServices(IServiceCollection services)
{
ServiceProvider = base.ConfigureServices(services);
Services = services;
ConstantsMock = new Mock<IConstants>();
services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object));
}
}
Make the ConstantsMock (the service you want to mock) available in your baseclass
Like this:
protected Mock<IConstants> __constantsMock;
__constantsMock = UnitTestStartup.ConstantsMock;
have every unit test class inherit from your baseclass
override the __constantsMock with a new object and you're done
I am working on an app which uses active directory to retrieve users. Sometimes I need to work on the app but AD is not available. I use a wrapper class to retrieve the AD user. I would like to inject a different class based on the configuration. I was thinking on using an appSetting that would tell me the current configutarion and decide what type to use when injecting. Is it possible to get the current configuration without using a Web.config transform? Is it possible to inject objects using Unity based on Web.config transformations? Can you recommend a better approach?
[UPDATE]
I have a user repository class that loads the users from AD. All I need is to be able to change the implementation of this repository class so that when AD is unavailable I can load the users a different way. This would only be used for development, production would always access AD and retrieve users.
You can use preprocessor directives:
#if DEBUG
// register fake repository
#else
// register AD repository
#endif
Well, Dependency Injection is incredibly powerful, agile, and creates a separation of concerns. The pitfall in your approach will come from validation. You see, with this approach you have to choose a concrete implementation.
So how will you call those two classes?
public class LogToText : ILogger
{
public void LogMessage(string message) { }
}
public class LogToEvent : ILogger
{
public void LogMessage(string message) { }
}
You have these two implementations, but when you pass the interface to:
public class AD
{
public AD(ILogger logger) { }
}
So the question will be do you feel that you can properly validate to choose the proper implementation effectively. Otherwise, Dependency Injection may not work well. We don't entirely know the usage or goal, so our advice may not be truly beneficial. Hopefully you see what I mean, because you'll have to see if you can't test a particular way.
You could use an Abstraction for this:
public interface IPersonService
{
IEnumerable<Person> Find(PersonSearchParameters searchParams);
Person GetByAccountName(string accountName);
[ETC...]
}
Then both your AD and Development implements this interface.
To make things easier, I suggest using StructureMap IoC, so you can easily do this:
x.For<IPersonService>.Use<ActiveDirectoryPersonService>(); //for production
or
x.For<IPersonService>.Use<MockPersonService>(); //for development
When using this you can, for instancce:
public class TestController : Controller
{
IPersonService _service;
public TestController(IPersonService service)
{
_service = service;
}
}
Instead of using an XML file for configuration in this case, I suggest using the Fluent code of Structure Map, it's better when refactoring and to avoid mistyping because it compiles.
StructureMap:
http://structuremap.net
Easy Installable via NuGET
A different approach would be to use the build configuration, read back from the assembly.
var buildConfiguration = typeof(Program).Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>()?.Configuration;
if (buildConfiguration == "Debug")
{
// register fake repository
}
else
{
// register AD repository
}
Then it is safer to apply refactorings or automatic code clean up (e.g. ReSharper etc.). Depending on your current configuration, code cleanup can otherwise remove unused usings. What then leads to build issues if an other configuration is used.
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.