Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Can I have multiple commands in a single class?

10 REPLIES 10
Reply
Message 1 of 11
Anonymous
1026 Views, 10 Replies

Can I have multiple commands in a single class?

Hi!

 

I'm still new to Autodesk plugins and since I didn't find an answer to my question I wanted to know if I could have 2 or more external commands in a single class?

 

I'm trying to connect Revit and SAP PLM and my goal is to create commands for Material upload, download and update. Since I'm more of a Java person I'm used to creating a class and class/object related methods in that class. I guess what I really want to know is that if I can use class methods as commands? Or should I just create multiple classes in a single .cs file and make each class implement IExternalCommand?

 

If I didn't phrase my question well enough try to be understanding because English is not my first language. Also if you have any questions about what I'm talking here don't hesitate to ask them in the comments.

Tags (3)
10 REPLIES 10
Message 2 of 11
ollikat
in reply to: Anonymous

Hi

 

Briefly, You cannot represent commands with methods within a single class.

 

But actually you don't need to implement IExternalCommand interface over and over again either. I would encourage you to investigate an approach where you have a base class that implements IExternalCommand. Within the Excute() method of this base class, you would call some (of your own made) virtual methods which are overriden in the deriving classes. The behaviour of certain command depends from the implementation of these methods.

 

So for example something like follows:

class BaseCommand : IExternal command
{
  public virtual Result Execute(...)
  {
    this.DoSomething();
  }
  
  protected abstract bool DoSomething();
}

class Upload : BaseCommand
{
  protected override bool DoSomething()
  {
    // Uploading stuff...
  }
}

class Download : BaseCommand
{
  protected override bool DoSomething()
  {
    // Downloading stuff...
  }
}

 

This is something similar what is also called as a "Template method". See more from Template method pattern in wiki.

Message 3 of 11
Anonymous
in reply to: ollikat

That's about the same conclusion I arrived on. Thanks for your input.

Message 4 of 11
MiguelVJC82W
in reply to: Anonymous

I keep getting the error not all code paths return a value.

 

Also isn't the "this.xxx" only meant for Macros?

 

And shouldn't it be an abstract class if it contains an abstract bool?

Message 5 of 11
ollikat
in reply to: MiguelVJC82W

- The first one is simply a generic error from the compiler and tries to tell you that with some conditions (if / else) the code execution never gets to any return statement although function should return something
- using "this" in front of member- variable/property/method is a standard C++/C# syntax, not to do especially with macros
- At least C# doesn't force you to use "abstract" in front of class, but it is probably recommended to have it explicitly.
Message 6 of 11
MiguelVJC82W
in reply to: ollikat

I still cant seem to get the code to compile without errors

 

using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using System;
using Autodesk.Revit.Attributes;

namespace Blank
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]


     abstract class CmdCombo : IExternalCommand
      {
           public virtual Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
           {
             DoSomething();

              return Result.Succeeded;
           }

         protected abstract bool DoSomething();
       }

 

     class Upload : CmdCombo
       {
           protected override bool DoSomething()
             {
             //Uploading stuff...

               UIApplication uiapp = commandData.Application;

              // Built-in Revit commands are listed in the
             // PostableCommand enumeration

              RevitCommandId id_built_in
               = RevitCommandId.LookupPostableCommandId(
              PostableCommand.ExportCADFormatsDXF);

              uiapp.PostCommand(id_built_in);
             }
        }

 

        class Download : CmdCombo
         {
            protected override bool DoSomething()
                   {
                   // Downloading stuff...
                  Autodesk.AutoCAD.Interop.AcadApplication a = new Autodesk.AutoCAD.Interop.AcadApplication();

                   a.Visible = true;

                   Autodesk.AutoCAD.Interop.AcadDocument doc
                  = a.Documents.Application.ActiveDocument;

                  double[] stpoint = new double[3];
                  double[] enpoint = new double[3];
                 stpoint[0] = 5;
                 stpoint[1] = 5;
                 stpoint[2] = 0;
                 enpoint[0] = 12;
                  enpoint[1] = 3;
                   enpoint[2] = 0;

                 doc.ModelSpace.AddLine(stpoint, enpoint);

                   doc.SaveAs("C:/tmp/testline.dwg");

                  a.Quit();
                   }
           }

}

 

Message 7 of 11
mhannonQ65N2
in reply to: MiguelVJC82W

The DoSomething method doesn't have a commandData parameter. You need to modify the abstract method definition and the definitions of the overrides to add that parameter and pass that parameter to where you call it in the Execute method.

Message 8 of 11
MiguelVJC82W
in reply to: Anonymous

Do you mean by adding it in between the brackets like so? I've gotten rid of the compiling error with CommandData for the Upload Class but It's still saying not all paths return a value though. 

 

using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using System;
using Autodesk.Revit.Attributes;

namespace Blank
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]


     abstract class CmdCombo : IExternalCommand
      {
           public virtual Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
           {
             DoSomething(commandData);

              return Result.Succeeded;
           }

         protected abstract bool DoSomething(ExternalCommandData commandData);
       }

 

     class Upload : CmdCombo
       {
           protected override bool DoSomething(ExternalCommandData commandData)
             {
             //Uploading stuff...

               UIApplication uiapp = commandData.Application;

              // Built-in Revit commands are listed in the
             // PostableCommand enumeration

              RevitCommandId id_built_in
               = RevitCommandId.LookupPostableCommandId(
              PostableCommand.ExportCADFormatsDXF);

              uiapp.PostCommand(id_built_in);
             }
        }

 

        class Download : CmdCombo
         {
            protected override bool DoSomething(ExternalCommandData commandData)
                   {
                   // Downloading stuff...
                  Autodesk.AutoCAD.Interop.AcadApplication a = new Autodesk.AutoCAD.Interop.AcadApplication();

                   a.Visible = true;

                   Autodesk.AutoCAD.Interop.AcadDocument doc
                  = a.Documents.Application.ActiveDocument;

                  double[] stpoint = new double[3];
                  double[] enpoint = new double[3];
                 stpoint[0] = 5;
                 stpoint[1] = 5;
                 stpoint[2] = 0;
                 enpoint[0] = 12;
                  enpoint[1] = 3;
                   enpoint[2] = 0;

                 doc.ModelSpace.AddLine(stpoint, enpoint);

                   doc.SaveAs("C:/tmp/testline.dwg");

                  a.Quit();
                   }
           }

}

Message 9 of 11
mhannonQ65N2
in reply to: Anonymous

You need to add `return true;` to the end of each of your DoSomething methods.

Message 10 of 11
MiguelVJC82W
in reply to: Anonymous

Ok I get it to compile now. Everything builds correctly but I'm getting an error when I try to launch the command from my Custom Button within Revit. 

 

"Revit cannot run the external command "Combo". Contact the ...

 

System.MissingMethodException 

 

Constructor on Type 'Bank.Combo' not found "

Message 11 of 11
ollikat
in reply to: MiguelVJC82W

The following...

"Bank.Combo"

Seems to have multiple typos / differences when compared to code above:

Bank"-> Blank
Combo -> CmdCombo"

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community