Pergunta

Estou tendo um problema com relação aos namespaces usados ​​pelas minhas referências de serviço.Eu tenho vários serviços WCF, digamos, com o namespace MyCompany.Services.MyProduct (os namespaces reais são mais longos).
Como parte do produto, também estou fornecendo um exemplo de site C# .NET.Este aplicativo da web usa o namespace MyCompany.MyProduct.

Durante o desenvolvimento inicial, o serviço foi adicionado como referência de projeto ao site e utilizado diretamente.Usei um padrão de fábrica que retorna uma instância de objeto que implementa MyCompany.Services.MyProduct.IMyService.Até agora tudo bem.

Agora quero mudar isso para usar uma referência de serviço real.Depois de adicionar a referência e digitar MyCompany.Services.MyProduct na caixa de texto do namespace, ele gera classes no namespace MinhaEmpresa.MeuProduto.MinhaEmpresa.Serviços.MeuProduto. RUIM! Eu não quero ter que mudar using diretivas em vários lugares só porque estou usando uma classe proxy.Então tentei acrescentar o namespace com global::, mas isso não é aceito.

Observe que eu ainda não havia excluído as referências originais do assembly e os "tipos de reutilização" estão ativados, mas aparentemente nenhuma reutilização foi feita. No entanto, não quero manter as referências de montagem no meu site de amostra para que funcione de qualquer maneira.

A única solução que encontrei até agora é definir o namespace padrão para meu aplicativo da web como MyCompany (porque não pode estar vazio) e adicionando a referência de serviço como Services.MyProduct.Suponha que um cliente queira usar meu site de exemplo como ponto de partida e altere o namespace padrão para OtherCompany.Whatever, isso obviamente interromperá minha solução alternativa.

Existe uma boa solução para este problema?

Para resumir:Quero gerar um proxy de referência de serviço no namespace original, sem fazer referência ao assembly.

Observação:Eu tenho visto essa questão, mas não foi fornecida nenhuma solução aceitável para meu caso de uso.


Editar:Como sugeriu John Saunders, enviei alguns comentários à Microsoft sobre isso:
Item de feedback no Microsoft Connect

Foi útil?

Solução

Eu adicionei um redação desta solução para o meu blog.Na verdade, a mesma informação, mas talvez um pouco menos fragmentada

Eu encontrei uma alternativa para usar svcutil.exe para realizar o que quero.Isso (imo) torna a atualização da referência de serviço mais fácil do que executar novamente o utilitário.

Você deve especificar explicitamente um uri de namespace em seu ServiceContract e DataContracts (veja mais abaixo para comentar).

[ServiceContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public interface IService
{
    [OperationContract]
    CompositeType GetData();
}

[DataContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public class CompositeType
{
    // Whatever
}

O namespace pode ser qualquer coisa, mas tecnicamente precisa ser um uri válido, então escolhi esse esquema.Talvez você precise construir manualmente para que as coisas funcionem mais tarde, então faça isso.

Feito isso, habilite o Mostrar todos os arquivos opção no Solution Explorer.Expanda a referência de serviço adicionada anteriormente.Clique duas vezes no Reference.svcmap arquivo.

Haverá um <NamespaceMappings /> elemento, que você precisará editar.Continuando meu exemplo:

<NamespaceMappings>
    <NamespaceMapping
        TargetNamespace="http://company.com/MyCompany.Services.MyProduct"
        ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>

Salve o arquivo, clique com o botão direito na referência do serviço e selecione Referência do serviço de atualização.

Você pode adicionar quantos mapeamentos precisar (na verdade, precisei de dois).O efeito é o mesmo que o svcutil /namespace: abordagem, mas sem ter que usar o próprio utilitário de linha de comando, facilitando a atualização.

Diferença com svcutil

A desvantagem dessa abordagem é que você precisa usar mapeamentos explícitos de namespace.Usando svcutil, você tem a opção de mapear tudo que não foi explicitamente mapeado desta forma (a solução à qual John Saunders estava se referindo):

svcutil /namespace:*,MyCompany.Services.MyProduct ...

Você pode pensar em usar:

<NamespaceMappings>
    <NamespaceMapping
        TargetNamespace="*"
        ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>

mas isso vai não funciona, porque o Visual Studio já adiciona implicitamente esse mapeamento, apontando para o nome do namespace gerado do qual estamos tentando nos livrar.A configuração acima fará com que o Visual Studio reclame sobre uma chave duplicada.

Namespaces explícitos de anúncios:
Quando nenhum namespace explit é especificado em seu código, ele parece que o .NET irá gerar um uri no formato http://schemas.datacontract.org/2004/07/MyCompany.Services.MyProduct.Você poderia mapear isso tão bem quanto os namespaces explícitos no meu exemplo, mas não sei se há alguma garantia para esse comportamento.Portanto, usar um namespace explícito pode ser melhor.

Observação:mapear dois TargetNamespaces para o mesmo ClrNamespace parece interromper a geração de código

Outras dicas

Seu caso de uso estava errado.

Em primeiro lugar, você nunca deveria ter incluído o serviço como referência.

Acredito que svcutil.exe aceitará uma opção especificando o namespace completo a ser usado.

No VS2010 e em versões posteriores, existe uma maneira de configurar namespaces personalizados.No gerenciador de soluções, selecione "Mostrar todos os arquivos", abra "Referências da Web" na árvore de soluções, selecione o serviço, selecione o nó Reference.map, mostre as propriedades e defina a propriedade Namespace da ferramenta personalizada.

Infelizmente não tenho reputação suficiente para mostrar uma captura de tela.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top