gRP C ошибки в WPF. NET Core - PullRequest
       3

gRP C ошибки в WPF. NET Core

0 голосов
/ 23 марта 2020

Я хочу создать простой проект WPF Core, gRP C. Этот «код» прекрасно работает в моем приложении. NET Core Console, однако WPF кажется чем-то особенным.

Proto File

syntax = "proto3";

option csharp_namespace = "MyProtoNamespace";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

gRP C Сервер

создал шаблон по умолчанию в Visual Studio 2019 ( использует. NET Core 3.1 )

Консольное приложение (работает отлично)

создано по умолчанию. NET Базовое консольное приложение -> добавило файл Proto с сервера на клиент и изменено gRP C Классы-заглушки на Только для клиента

использует:. NET Core 3.1

имеет следующие NuGets:

  • Grp c .Tools
  • Grp c. Net .Client
  • Google.Protobuf

код

static async Task Main(string[] args) // works perfectly
{
    using var channel = GrpcChannel.ForAddress("https://localhost:5001");
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(new HelloRequest { Name = "GreeterClient" });

    System.Console.WriteLine("Greeting: " + reply.Message);
    System.Console.WriteLine("Press any key to exit...");
    System.Console.ReadKey();
}

WPF. NET Core

создан по умолчанию WPF. NET Базовое приложение -> добавлено Прото-файл с сервера на клиент и изменил классы заглушки gRP C на только для клиента

использует:. NET Core 3.1

имеет следующие NuGets:

  • Grp c .Tools
  • Grp c. Net. Клиент
  • Google.Protobuf

код

Loaded += async delegate
{
    using var channel = GrpcChannel.ForAddress("https://localhost:5001");
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(new HelloRequest { Name = "GreeterClient" });
};

ПРОБЛЕМА

Могу НЕ создавать приложение WPF

ошибки:

Тип или имя пространства имен 'MyProtoNamespace' не существует в пространстве имен 'MyWPFNameSpace' (у вас отсутствует ссылка на сборку?)

1 Ответ

0 голосов
/ 24 марта 2020

Эта проблема связана с пакетом Grpc.Tools и специальным процессом сборки приложений WPF. Пакет Grpc.Tools отвечает за компиляцию файла .proto и генерацию классов обслуживания.

Решение состоит в том, чтобы переместить экземпляр клиента gRP C в отдельную. NET Базовую сборку библиотеки классов (проект ). Просто распакуйте этот код в класс, например GrpcServiceProvider в этой новой сборке. Пусть GrpcServiceProvider возвращает экземпляр клиента gRP C. Теперь из вашей сборки WPF обратитесь к сборке базовой библиотеки. NET и классу GrpcServiceProvider для получения экземпляра клиента.
Это исправит ошибку сборки и улучшит дизайн приложения.

Не забывайте, что GrpcChannel реализует IDisposable. Это означает, что GrpcServiceProvider должен также реализовать его и правильно распорядиться ресурсами.

. NET Проект библиотеки базовых классов

public class GrpcServiceProvider : IDisposable 
{
  public GrpcServiceProvider()
  {
    this.ServiceUrl = "https://localhost:5001";
    this.DefaultRpcChannel = new Lazy<GrpcChannel>(GrpcChannel.ForAddress(this.ServiceUrl));
  }

  public Greeter.GreeterClient GetGreeterClient() => this.GreeterClient ??= new Greeter.GreeterClient(this.DefaultRpcChannel.Value);

  #region IDisposable Support
  private bool disposedValue = false; // To detect redundant calls

  protected virtual void Dispose(bool disposing)
  {
    if (!disposedValue)
    {
      if (disposing)
      {
        if (this.DefaultRpcChannel.IsValueCreated)
        {
          this.DefaultRpcChannel.Value.Dispose();
        }
      }

      // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
      // TODO: set large fields to null.

      disposedValue = true;
    }
  }

  // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
  // ~GrpcServiceProvider()
  // {
  //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
  //   Dispose(false);
  // }

  // This code added to correctly implement the disposable pattern.
  public void Dispose()
  {
    // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
    Dispose(true);
    // TODO: uncomment the following line if the finalizer is overridden above.
    // GC.SuppressFinalize(this);
  }

  #endregion IDisposable Support

  private Lazy<GrpcChannel> DefaultRpcChannel { get; set; }    
  private string ServiceUrl { get; set; }    
  private Greeter.GreeterClient GreeterClient { get; set; }
}

Проект WPF

Loaded += async delegate
{
    using var serviceProvider = new GrpcServiceProvider();
    var client = serviceProvider.GetGreeterClient();
    var reply = await client.SayHelloAsync(new HelloRequest { Name = "GreeterClient" });
};
...