Hello. I want to use DI and IoC in my plugin. And I want to inject my dependencies in constructor. To do this, I need to get control of command class creation. Let assume we have such code in command class
[Transaction(TransactionMode.Manual)] class CmdTypeToMarkSeparateType : IExternalCommand { private ISomeService _service { get; set; } // some service should be passed to command. // In fact it is constructor injection public CmdTypeToMarkSeparateType(ISomeService service) { _service = service; } public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { TaskDialog.Show("Test name", _service.message); return Result.Succeeded; } }
to make this possible, I should be able to control creation of command classes. In AutoCAD, I achieve this, by registrering all commands by myself and wrapping them in lambda, where I am extracting all constructor parameters by my self, using my DI container. How can I achieve this in Revit? Let assume, I have such code:
private void AddPushButton(RibbonPanel panel) { PushButton pushButton = panel.AddItem(new PushButtonData("HelloWorld", "HelloWorld", @"D:\Sample\HelloWorld\bin\Debug\HelloWorld.dll", "HelloWorld.CsHelloWorld")) as PushButton; // Set ToolTip and contextual help pushButton.ToolTip = "Say Hello World"; ContextualHelp contextHelp = new ContextualHelp(ContextualHelpType.Url, "http://www.autodesk.com"); pushButton.SetContextualHelp(contextHelp); // Set the large image shown on button pushButton.LargeImage = new BitmapImage(new Uri(@"D:\Sample\HelloWorld\bin\Debug\39-Globe_32x32.png")); }
As we can see we pass only classname of command class. Maybe there is a way to do something like this:
private void AddPushButton(RibbonPanel panel, IServiceContainer services) { // Add push button without command PushButton pushButton = panel.AddItemSomeWay(); pushButton.onClick = () => { // Create command class using my DI container and pass dependencoes var cmdClass = services.GetInstance<CmdTypeToMarkSeparateType>(); // call execute method cmdClass.Execute(); } }
Or maybe there is a way to override some default Revit activator, where it creates command class instances? Or maybe there is a way to pass parameters to execute method (it is the worst method), and I will get my service container directly in Execute method?