2015-10-28 5 views
0

Итак, ExternalDefinitionCreationOptions had a spelling error в API Revit 2015, который был исправлен в API 2016 года.Тот же код для создания параметров в Revit 2015 + 2016

Я пытаюсь сделать мое приложение максимально совместимым с текущей версией + предыдущим, но на этот раз я даже не могу его скомпилировать, так как я могу ссылаться только на одну из двух DLL-библиотек API, а ExternalDefinitionCreationOptions играет роль большую роль в этом процессе.

Код следующее:

private static Definition GetSimpleParameterDefinition(UIApplication uiApp, Document doc, DefinitionGroup defGroup, string name) 
{ 
    var definition = defGroup.Definitions.FirstOrDefault(d => d.Name == name); 
    if (definition != null) return definition; 

    var parameterType = ParameterType.Text; 

    var defOptions = new ExternalDefinitionCreationOptions(name, parameterType); 
    BuiltInCategory target = BuiltInCategory.OST_Furniture; 
    var cat = doc.Settings.Categories.get_Item(target); 

    var catSet = uiApp.Application.Create.NewCategorySet(); 
    catSet.Insert(cat); 

    definition = defGroup.Definitions.Create(defOptions); 

    return definition; 
} 

Я читаю о DI и IoC, но все образцы имеют весь код под контролем, а не ссылки на сторонние API и борьбы с ней. У меня кончились идеи.

Любые мысли о том, как это сделать?

ответ

2

dynamic in C# позволяет использовать позднюю переписку. Тогда я хотел бы предложить некоторые размышления, чтобы instante объекта, как «логика» ниже (не тестировались, должно быть завершено)

Type t = System.Reflection.Assembly.GetExecutingAssembly().GetType("ExternalDefinitionCreationOptions"); 
dynamic defOptions = t.GetConstructor().Invoke(); 

Обратите внимание, что динамического отличается от вара. Ваш код использует var как способ позволить компилятору решить тип ... теперь динамический будет определять только тип во время выполнения.

+0

Привет @AugustoGoncalves, это похоже на отличный способ достичь этого, но 'GetExecutingAssembly()' (также 'GetCallingAssembly()') не возвращаются в сборе RevitAPI , оба возвращают мою сборку. Я даже попытался пройти через стек, чтобы получить Revit, но не успел. Мое приложение работает в Revit Initialization, поэтому я не знаю, является ли это причиной того, что он не работает так, как вы предполагали. –

2

Использование базового кода от Augusto (upvoted) и многое другое исследование Reflection я был в состоянии написать это решение:

var assemblies = System.Reflection.Assembly.GetExecutingAssembly().GetReferencedAssemblies(); 
var assemblyName = assemblies.First(a => a.Name == "RevitAPI"); 
Assembly revitAssembly = Assembly.Load(assemblyName); 

Type t = revitAssembly.GetType("Autodesk.Revit.DB.ExternalDefinitionCreationOptions"); // For Revit2016 
if (t == null) t = revitAssembly.GetType("Autodesk.Revit.DB.ExternalDefinitonCreationOptions"); // For Revit2015 

var types = new Type[1] { t }; 
var constructor = t.GetConstructors()[0]; 
dynamic defOptions = constructor.Invoke(new object[] { item.Name, parameterType }); 
+0

красиво сделано! :-) –

1

Почему бы не использовать условной компиляции?

#if REVIT2015 
    var defOptions = new ExternalDefinitonCreationOptions(name, parameterType); 
#else 
    var defOptions = new ExternalDefinitionCreationOptions(name, parameterType); 
#endif 

Вы должны определить REVIT2015 символ условной компиляции в проекте Revit 2015 (параметры проекта, вкладку Построить).

Конечно, это работает, только если у вас есть два отдельных проекта VS, с исходным проектом и проектом, где файлы связаны с файлами исходного проекта.

+0

Hi @Maxence, я использую этот подход в различных ситуациях, с новыми функциями, которые идут на одну версию, а не на другую. Но этот случай был основной функцией продукта, мне нужно было работать без условной компиляции. –

+0

да! это получает мой голос! это именно тот ответ, на который мне хотелось только прочитать резюме в полученном мной электронном письме: «Итак, у ExternalDefinitionCreationOptions была ошибка орфографии в API Revit 2015, которая была исправлена ​​в API 2016 года. Я пытаюсь сделать свое приложение совместимым с возможно с текущей версией ... ». круто! –

0

Я полностью согласен с подходом maxence выше.

Я также предлагаю разместить всю условную компиляцию в один модуль совместимости и экспортировать ее функциональность как методы или свойства, например. определяя способ, как это:

ExternalDefinitionCreationOptions 
    NewExternalDefinitionCreationOptions(
    string name, 
    ParameterType parameterType) 
{ 
    #if REVIT2015 
    return new ExternalDefinitonCreationOptions(name, parameterType); 
    #else // if not REVIT2015 
    return new ExternalDefinitionCreationOptions(name, parameterType); 
    #endif // REVIT2015 
} 

Я реализовал это здесь:

https://github.com/jeremytammik/the_building_coder_samples/blob/master/BuildingCoder/BuildingCoder/Util.cs#L1209-L1225

получайте удовольствие!

веселит

Jeremy

+0

Привет @Jeremy, спасибо за ответ. Но как вы можете сделать этот класс Util без проблем между Revit 2015 и 2016 в той же DLL? –

+0

ahaa, в той же DLL. ok, что исключает условную компиляцию. есть еще одно простое решение: вы можете проверить свойство Application.VersionNumber и затем вызвать соответствующий метод с помощью Invoke. –

+0

ДА! Решение Augusto было потрясающим началом для меня, я только что опубликовал окончательное и рабочее решение после этого. –

0

Обновленный ответ для обработки как Revit 2015 и Revit 2016 API в рамках одного надстройки.

Вы действительно хотите это сделать?

Ну, если вы настаиваете, то здесь идет:

#region Compatibility fix for spelling error change 
/// <summary> 
/// Wrapper to fix a spelling error prior to Revit 2016. 
/// </summary> 
public class SpellingErrorCorrector 
{ 
    static bool _in_revit_2015_or_earlier; 
    static Type _external_definition_creation_options_type; 

    public SpellingErrorCorrector(Application app) 
    { 
    _in_revit_2015_or_earlier = 0 
     <= app.VersionNumber.CompareTo("2015"); 

    string s 
     = _in_revit_2015_or_earlier 
     ? "ExternalDefinitonCreationOptions" 
     : "ExternalDefinitionCreationOptions"; 

    _external_definition_creation_options_type 
     = System.Reflection.Assembly 
     .GetExecutingAssembly().GetType(s); 
    } 

    object NewExternalDefinitionCreationOptions(
    string name, 
    ParameterType parameterType) 
    { 
    object[] args = new object[] { 
     name, parameterType }; 

    return _external_definition_creation_options_type 
     .GetConstructor(new Type[] { 
     _external_definition_creation_options_type }) 
     .Invoke(args); 
    } 

    public Definition NewDefinition(
    Definitions definitions, 
    string name, 
    ParameterType parameterType) 
    { 
    //return definitions.Create( 
    // NewExternalDefinitionCreationOptions()); 

    object opt 
     = NewExternalDefinitionCreationOptions(
     name, 
     parameterType); 

    return typeof(Definitions).InvokeMember(
     "Create", BindingFlags.InvokeMethod, null, 
     definitions, new object[] { opt }) 
     as Definition; 
    } 
} 
#endregion // Compatibility fix for spelling error change 

Использование:

static Util.SpellingErrorCorrector 
    _spellingErrorCorrector = null; 

Application app = doc.Application; 

if(null == _spellingErrorCorrector) 
{ 
    _spellingErrorCorrector 
    = new Util.SpellingErrorCorrector(app); 
} 

DefinitionGroup group = sharedParametersFile 
    .Groups.Create("Reinforcement"); 

def = _spellingErrorCorrector.NewDefinition(
    group.Definitions, "ReinforcementParameter", 
    ParameterType.Text); 

Непроверено!

Cheers,

Джереми

+0

Спасибо Джереми, это очень то, что я разработал несколько дней назад -> http://stackoverflow.com/a/33401274/228160 –