Dependency Injection and command classes
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
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?
