Dependency injection in custom workflow activity - c#

I have a standard application that has a workflow. The customer can customize the workflow in the designer. Now we are making some custom activities for a specific customer. The custom activity is communicating against the business layer by a interface. How do I give the interface an implementation of that interface?
It is very important that the standard application doesn't know about the interface and implementation of that interface because it is custom code for that specific customer. The activity is found by standard workflow so that works already.
I see a lot of information about extensions but I don't really know how it works.
Custom activity
public sealed class GetDealerDetails : CodeActivity
{
/////// <summary>
/////// The dealer controller with all the businesslogic.
/////// </summary>
////private readonly IDealerController _dealerController;
[Inject]
public IDealerController DealerController { private get; set; }
////public GetDealerDetails()
////{
////}
////[Inject]
////public GetDealerDetails(IDealerController dealerController)
////{
//// _dealerController = dealerController;
////}
protected override void Execute(CodeActivityContext context)
{
Dealer dealer = DealerController.GetDealerDetails(5);
}
}
I use Ninject in my standard application. I tried to use constructor injection and property injection but it doesn't work. The DealerController stays null.
Edit
The rest of the code can be found here: Inject custom code in standard application

Import is that you have to use the workflow application wrapper I provide with ninject. Only with that I can build up the activities. The trick is the following: you cannot use constructor injection with custom workflow activities. Activities are very special in WF. Usually when you have coded workflow you build them up we the new operator in a lambda expression which is then lazy executed. So my ninject extension can only work its magic when the activities are already built up. Therefore you need to pass in the root activities of your activity tree in the workflow application of ninject. This does then internally resolve the whole activity tree und injects all properties which are decorated with the inject attribute.
But your actual problem was a bug in the library which I have fixed now. The BookmarkInfo decorator assumed that the scope info is always set and this wasn't the case.

Extensions are what the framework provides for injection in workflows. When you execute the workflow you add all dependencies that you will use in your activities.
[Dependency]
public IMyService MyService{ get; set; }
WorkflowApplication instance = new WorkflowApplication(myWorkflow, inParameters);
instance.Extensions.Add(MyService);
instance.Run();
And then you can get the extension in your activity in order to use it.
protected override void Execute(NativeActivityContext context){
var myservice = context.GetExtension<IMyService>();
myservice.MyMethod();
}
I hope it helps.

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.

Nancy IoC per request auto registration

We have an ASP.NET REST service implemented with Nancy (and TinyIoc), which interfaces with a quite large legacy application. We would like to transition to full dependency injection. At the moment most of our modules instantiate the controllers directly, and takes a context class which holds the request information using the NancyContext Context property. Something like this:
public FooModule(ILegacyService legacyService) {
Get["/"] = parameters => new FooController(new RequestContext(Context), legacyService).GetFoo();
}
We would like to inject the controllers directly in the module, and get everything handled by the super-duper-happy-path :)
Our problems all stem from the fact that we need information from NancyContext. The url, headers etc. So we have attempted various approaches to get to dependency injection nirvana.
Attempting to inject controllers failed, since they're instantiated in application scope, and so any dependency to RequestContext would not have the current context information. Even registering RequestContext in ConfigureRequestContainer did not ripple through to all dependants, and they would hold references to an out of date RequestContext.
We have tried to property inject the context using IRequestStartup, and this seemed successful, until we ran into concurrency issues. Simultaneous requests in different threads would overwrite the application scope RequestContext.
We found out that we could call container.AutoRegister() in ConfigureRequestContainer, but this resulted in severe lag, since registrations takes seconds with the amount of types we have.
Using AsPerRequestSingleton() in ConfigureApplicationContainer seems like it will register once, and then instantiate per request, but there doesn't seem to be a way to get auto registration to adhere to this.
It seems like we need to register all types manually, and keep this configuration up to date manually. Is this the case? We really would prefer to have some type of auto registration with per request lifetime.
I have created a small test project (https://github.com/Rassi/NancyIocTest) in which I attempted some of these solutions.
Using DefaultNancyAspNetBootstrapper you can create your own auto registering like this:
public class Bootstrapper : DefaultNancyAspNetBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
var assemblyClasses = Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsClass);
foreach (var assemblyClass in assemblyClasses)
{
var interfaces = assemblyClass.GetInterfaces();
if (interfaces.Count() == 1)
{
container.Register(interfaces[0], assemblyClass).AsPerRequestSingleton();
}
}
}
Everything is then instantiated per request, and you can inject context information using RequestStartup():
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
base.RequestStartup(container, pipelines, context);
var requestUrl = container.Resolve<IRequestUrl>();
requestUrl.Context = context;
}
}
This is a simple proof of concept, which will find classes which implement one interface, and register it to that. A couple of issues should probably be handled, such as: Registering classes implementing multiple interfaces (perhaps using the convention of registering Name to IName). And also handling multiple classes registering the same interface.

Dependency injection based on configuration?

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.

Castle Windsor Ioc container doesn't resolve subdependencies

I have 'standard' MVC application in next structure: UI (MVC), Business logic and data access using FluentNHibernate. I've done all steps for registering in castle container my components as described in castle documentation, used FluentRegistration API. So, all components were registered using WIndsor Installers like this:
container.Register(Classes.FromThisAssembly()
.BasedOn(typeof(IHandlerBase<>))
.WithService.AllInterfaces()
.LifestyleTransient());
In this code IHandlerBase - generic interface from which derives all my nested classes in business logic. Data access registered in same way and when I start my app all my components and services registered in container. All dependencies in MVC project relatively to BL resolved, but when I need my dependencies in business logic relatively to DataAccess they didn't. Stub example of my modules:
MVC
public ILogger Logger { get; set; } // Resolved, not null
public IHandlerBase<FooRerquest> FooHandler<FooRequest> { get; set; } // Resolved, not null
// Call Foohandler method
FooHandler.MethodName() { ... } // Here works fine
BusinessLogic
public ILogger Logger { get; set; } // Unresolved, null
public IRepository <FooCommand> FooRepository<FooCommand> { get; set; } // Unresolved, null
// Call FooRepository method
FooRepository.MethodName() { ... } // Doesn't work, catch ArgumentNullException
ILogger is a Castle NLog Facility
What and where I do in wrong way?
Thanks, Andrew
It works in UI because Controllers are created via custom ControllerFactory which uses container usually.
If instances of your business logic classes are resolved as part of MVC classes, they should be resolved. If simply constructors are used to create instances of your business logic classes then they know nothing about IoC and all references can't be resolved.
I suggest you use constructor injection since it makes Dependency Injection more visible.

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.

Categories