2014-03-10 3 views
7

У меня есть две библиотеки, написанные на C#, которые я хотел бы использовать в приложении F #. Обе библиотеки используют один и тот же тип, однако я не могу убедить F # в проверке типа этого факта.Тип 'T' несовместим с типом 'T'

Вот простой пример использования типов взаимодействий Office. F # кажется особенно чувствительным к этим типам проблем. Кастинг на стороне F #, похоже, не помогает ситуации. Все три проекта имеют ссылку на одну и ту же сборку («Microsoft.Office.Interop.Excel», версия 14.0.0.0).

В проекте "project1" (С # проект):

namespace Project1 
{ 
    public class Class1 
    { 
     public static Microsoft.Office.Interop.Excel.Application GetApp() 
     { 
      return new Microsoft.Office.Interop.Excel.Application(); 
     } 
    } 
} 

В проекте "project2" (С # проект):

namespace Project2 
{ 
    public class Class2 
    { 
     Microsoft.Office.Interop.Excel.Application _app; 

     public Class2(Microsoft.Office.Interop.Excel.Application app) 
     { 
      _app = app; 
     } 
    } 
} 

В проекте (ые F # проект) "TestApp" :

[<EntryPoint>] 
let main argv = 
    let c2 = Project2.Class2(Project1.Class1.GetApp()) 
    0 

Какие-либо намеки?

Редактировать:

Изменения вызова Class2 «ы конструктора со следующей динамической литой решает эту проблему:

let c2 = Project2.Class2(Project1.Class1.GetApp() :?> Microsoft.Office.Interop.Excel.Application) 

Однако это неудовлетворительно, так как 1) динамическое, и 2) Я до сих пор не понимаю, почему оригинальная проверка типа не удалась.

+4

Я подозреваю, что ответ связан с компилятором F #, не понимающим правила эквивалентности типа не-PIA. – kvb

+2

+1 F # и C# работают несколько иначе с COM-взаимодействием, см. Там: http://apollo13cn.blogspot.se/2012/04/trick-in-f-interop.html –

ответ

2

COM interop. Когда вы ссылаетесь на COM-сборку, она фактически создаст сборку COM-взаимодействия для маршалинга между .NET и COM. Если у вас есть две сборки, ссылающиеся на одну и ту же COM-сборку, у вас может быть фактически две идентично сгенерированные сборки соединений.

Одним из решений и, откровенно говоря, лучшим дизайном в общем случае было бы создание интерфейсов в одной из двух сборок (или разделяемой третьей сборки), которые раскрывают функции, которые вы хотите публиковать, а вместо использования или потребления COM-типов используют эти интерфейсы.

namespace Project1 
{ 
    public interface IApplication 
    { 
     // application members here... 
    } 

    public class Class1 
    { 
     public static IApplication GetApp() 
     { 
      return new ExcelApplication(new Microsoft.Office.Interop.Excel.Application()); 
     } 

     private class ExcelApplication : IApplication 
     { 
      public ExcelApplication(Microsoft.Office.Interop.Excel.Application app) 
      { 
       this.app = app; 
      } 

      // implement IApplication here... 
     } 
    } 
} 
Смежные вопросы