Dependency Injection and command classes

Dependency Injection and command classes

Anonymous
Not applicable
2,331 Views
5 Replies
Message 1 of 6

Dependency Injection and command classes

Anonymous
Not applicable

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?

 

 

0 Likes
2,332 Views
5 Replies
Replies (5)
Message 2 of 6

Mustafa.Salaheldin
Collaborator
Collaborator

I don't know why you need to do so but try to create a static public variable/method in the external command and pass to it whatever you want the process it in the Execute method.


¯\_(ツ)_/¯
Let it work like a charm.

Mustafa Salaheldin


EESignature




Digital Integration Manager, DuPod

Facebook | Twitter | LinkedIn

0 Likes
Message 3 of 6

Anonymous
Not applicable

I want to implement constructor dependency injection, which is considered to be good practice in c#  development. I have managed to do it in AutoCad and it was really useful.   

0 Likes
Message 4 of 6

Anonymous
Not applicable

Hi,

 

Did you ever get a nicer solution for this?

0 Likes
Message 5 of 6

RichWhitfield
Participant
Participant

Testability, extensibility etc...all the standard arguments for programming to an interface.

0 Likes
Message 6 of 6

Kennan.Chen
Advocate
Advocate

I have implemented a DI framework in my add-in. I borrowed the SimpleContainer implementation from an early version of the ASP.NET Blazor framework while I was reading through its source code. The SimpleContainer is a singleton class that provides the registration and injection. And I have a ContainerObject base class that handles the constructor injection and property injection.

 

Actually there was a similar reply last year in which I shared my implementation.

Re: Register Services (Dependency Injection) - Autodesk Community - Revit Products