Arquitetura peculiar que liga o .NET ao AutoCAD fora de processo

5

Eu escrevi um conjunto de classes para interagir com o AutoCAD a partir de uma montagem .NET fora do processo, mas parece que a arquitetura e as interações da minha classe são incomuns. Eu estou lutando para encontrar uma maneira melhor de projetá-los.

Alguns antecedentes:

Estou lendo dados de vários milhares de desenhos do AutoCAD, coletando dados de listas de materiais, blocos de títulos e outras entidades. O AutoCAD pode ser interfaceado de outro processo de várias maneiras. Uma maneira é usar a biblioteca de tipos do AutoCAD COM, que organiza todas as chamadas e é relativamente lenta (cerca de 6 segundos por desenho). Uma maneira muito mais rápida é carregar uma DLL do .NET no processo do AutoCAD e executar o código lá. Este componente .NET expõe uma interface COM (vamos chamá-lo IAutoCADDataReader) que você pode chamar do mundo exterior. Se você chamar um método nessa interface, poderá coletar os dados e retornar um objeto que contenha todos os dados reunidos (chame-o de IDomainObject). Isso funciona bem e leva cerca de 200 ms (grande melhoria), já que a interação com o banco de dados do AutoCAD estava em andamento e você apenas empacotou um objeto complicado no final.

A parte acima do design estou feliz com. O que me incomoda é o que faço com o IDomainObject quando o coloco de volta no meu assembly .NET principal. É claro que é um _COMObject que eu posso converter para um IDomainObject, mas ele realmente não existe no meu assembly gerenciado, é um stub ou proxy. Quando eu leio seus dados, ele chama através do limite do processo. Se o AutoCAD for desligado, receberei um erro de RPC. Eu realmente gostaria que esse objeto existisse independentemente de sua fonte original. A solução natural é clonar e descartar o objeto COM.

Agora, geralmente, um método Clone está no próprio objeto. Isso se encaixa com SRP desde quem sabe mais sobre clonagem do que seria? Isso não é uma solução nesse caso, já que um método Clone nessa interface IDomainObject seria realmente executado no processo do AutoCAD e apenas me daria outro objeto COM. Assim, ignorando o SRP, escrevi uma função Clone privada no assembly gerenciado que percorre as várias matrizes e outros dados no IDomainObject e retorna um DomainObject totalmente gerenciado (não uma interface). Esse novo objeto agora pode existir independentemente do AutoCAD, pode fazer o que quiser no mundo gerenciado e não estará sujeito a erros de RPC.

Eu gosto do resultado final desse processo confuso desde que eu terminei com o que eu queria de uma forma bastante rápida, mas não posso deixar de pensar que esta é uma maneira estranha de arquitetar uma coisa dessas. Algum de vocês tem alguma sugestão sobre como esse design pode ser refatorado para torná-lo menos peculiar?

Outra crítica que poderia ser nivelada neste tipo de clonagem é que ela falha no princípio Open / Closed. Se eu estender qualquer um dos subtipos dentro do IDomainObject, a operação clone não estará mais correta. Eu teria que atualizar essa função de clone particular nesse momento. Isso realmente mostra como essa solução funciona por enquanto, mas viola vários princípios que provavelmente me morderão enquanto este projeto continua a evoluir. Como desenvolvedor de software interno, esse material será usado e evoluído por anos e não seria bom ter essas práticas ruins no começo.

    
por Mike 25.03.2015 / 18:09
fonte

1 resposta

3

Um método relativamente simples e genérico para passar objetos .NET sobre limites do processo é usar a serialização. Certifique-se de que seu DomainObject seja serializável, então você pode implementar seu método Clone serializando seu objeto em um fluxo de memória e desserializá-lo de lá dentro de seu componente principal fora de processo.

Usamos isso em conjunto com arquivos mapeados na memória como uma forma de IPC para passar uma hierarquia complexa de objetos, mas tenho certeza que isso funcionará na sua situação sem este detalhe técnico adicional (e se não: converta a memória fluxo para uma seqüência de caracteres, em seguida, a mecânica COM para passar seqüências de caracteres entre processos pode ser aplicada). Isso resolve exatamente os problemas que você descreveu acima: você não precisa escrever nenhum código para iterar sobre seus arrays internos (a serialização do .NET "magic" fará isso para você), e ao estender seus subtipos, não há nada para mudar em seu método clone.

    
por 25.03.2015 / 19:38
fonte