Windows Azure を使用するプロジェクトに取り組んでおり、worker ロール内で Web サービスを使用して情報を送信したいと考えています。私の質問は、サービス参照を追加せずに Web サービスを使用できますか? または、プロジェクトをAzureで公開するときに、サービス参照を変更する必要がないように特定の方法で追加するには?
質問する
978 次
1 に答える
3
チャネル ファクトリを使用して直接接続できます。以下は、オーバーライドするベース リポジトリ クラスのサンプルです。ここで、T は IMyService などのサービス コントラクトです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.WindowsAzure.ServiceRuntime;
namespace pageengine.clients
{
public class RepositoryBase<T> : IDisposable
{
#region Channel
protected String roleName;
protected String serviceName;
protected String endpointName;
protected String protocol = @"http";
protected EndpointAddress _endpointAddress;
protected BasicHttpBinding httpBinding;
protected NetTcpBinding tcpBinding;
protected IChannelFactory channelFactory;
protected T client;
protected virtual AddressHeader[] addressHeaders
{
get
{
return null;
}
}
protected virtual EndpointAddress endpointAddress
{
get
{
if (_endpointAddress == null)
{
var endpoints = RoleEnvironment.Roles[roleName].Instances.Select(i => i.InstanceEndpoints[endpointName]).ToArray();
var endpointIP = endpoints.FirstOrDefault().IPEndpoint;
if(addressHeaders != null)
{
_endpointAddress = new EndpointAddress(new Uri(String.Format("{1}://{0}/{2}", endpointIP, protocol, serviceName)), addressHeaders);
}
else
{
_endpointAddress = new EndpointAddress(String.Format("{1}://{0}/{2}", endpointIP, protocol, serviceName));
}
}
return _endpointAddress;
}
}
protected virtual Binding binding
{
get
{
switch (protocol)
{
case "tcp.ip":
if (tcpBinding == null) tcpBinding = new NetTcpBinding();
return tcpBinding;
default:
//http
if (httpBinding == null) httpBinding = new BasicHttpBinding();
return httpBinding;
}
}
}
public virtual T Client
{
get
{
if (this.client == null)
{
this.channelFactory = new ChannelFactory<T>(binding, endpointAddress);
this.client = ((ChannelFactory<T>)channelFactory).CreateChannel();
((IContextChannel)client).OperationTimeout = TimeSpan.FromMinutes(2);
var scope = new OperationContextScope(((IContextChannel)client));
addCustomMessageHeaders(scope);
}
return this.client;
}
}
protected virtual void addCustomMessageHeaders(OperationContextScope operationContextScope)
{
// Overidden
}
#endregion
#region CTOR
public RepositoryBase()
{
}
#endregion
#region IDisposable Members
public virtual void Dispose()
{
if (client != null)
{
try
{
((ICommunicationObject)client).Close();
}
catch
{
try
{
((ICommunicationObject)client).Abort();
}
catch { } // Die quietly.
}
}
if (channelFactory != null)
{
try
{
channelFactory.Close();
}
catch
{
try
{
channelFactory.Abort();
}
catch { } // Die quietly.
}
channelFactory = null;
}
_endpointAddress = null;
httpBinding = null;
tcpBinding = null;
}
#endregion
}
}
次に、公開環境とエミュレート環境の両方で機能するエンドポイントを検出します。このベースを拡張するクラスは次のようになります。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using pageengine.services.entities.account;
using pageengine.services;
namespace pageengine.clients.accounts
{
public class AccountsRepository : RepositoryBase<IAccounts>, IDisposable
{
#region CTOR
public AccountsRepository()
{
this.roleName = "EntitiesRole"; // Name of the role my service is on
this.endpointName = "HttpInternal"; // Name of the endpoint configured on that role. Can be internal or input, tcp or http.
this.serviceName = "Accounts.svc"; // Name of my service.
}
#endregion
}
}
サービスへの呼び出し (この場合は MVC コントローラー アクションから) は、次の形式になります。
public ActionResult ListAccounts()
{
using (var accountsRepository = new AccountsRepository())
{
return View("ListAccounts", accountsRepository.Client.ListAccounts());
}
}
于 2012-08-22T09:18:40.217 に答える