#wcf-lob-adapter
#wcf-lob-adapter
Вопрос:
Я пытаюсь создать веб-графический интерфейс для использования пользовательских разъемов на основе SDK на основе LOB-адаптера. В частности, я хотел бы просмотреть метаданные с помощью интерфейса IMetadataResolverHandler.
У меня возникли две проблемы:
Первая проблема возникает при попытке создать экземпляр пользовательского адаптера. Мой план состоит в том, чтобы получить экземпляр интерфейса IConnectionFactory, через который я мог бы получить новое подключение и подключиться к целевой LOB-системе.
Поскольку наиболее интересные методы в базовом классе Adapter защищены, я могу добиться успеха только с помощью отражения (пожалуйста, смотрите Пример кода ниже).
Вторая проблема возникает при попытке просмотреть метаданные из целевой системы. Метод Browse
в интерфейсе IMetadataResolverHandler ожидает экземпляр объекта MetadataLookup, который я понятия не имею, как получить.
Пожалуйста, смотрите пример кода ниже:
static void Main(string[] args)
{
var extension = new SqlAdapterBindingElementExtensionElement();
var adapter = (Adapter) Activator.CreateInstance(extension.BindingElementType);
var isHandlerSupportedMethodInfo = adapter.GetType().GetMethod("IsHandlerSupported", BindingFlags.NonPublic | BindingFlags.Instance);
var buildConnectionUri = adapter.GetType().GetMethod("BuildConnectionUri", BindingFlags.NonPublic | BindingFlags.Instance);
var buildConnectionFactory = adapter.GetType().GetMethod("BuildConnectionFactory", BindingFlags.NonPublic | BindingFlags.Instance);
if (isHandlerSupportedMethodInfo == null || buildConnectionUri == null || buildConnectionFactory == null)
{
Console.WriteLine("Not a LOB adapter.");
Environment.Exit(1);
}
var isHandlerSupportedTHandler = isHandlerSupportedMethodInfo.MakeGenericMethod(typeof(IMetadataResolverHandler));
var isMetadataBrowseSupported = (bool)isHandlerSupportedTHandler.Invoke(adapter, new object[] { });
if (!isMetadataBrowseSupported)
{
Console.WriteLine("Metadata retrieval not supported.");
Environment.Exit(1);
}
var bindingElement = (SqlAdapterBindingElement)adapter;
bindingElement.AcceptCredentialsInUri = false;
bindingElement.InboundOperationType = InboundOperation.TypedPolling;
bindingElement.PolledDataAvailableStatement = "EXEC [dbo].[usp_IsDataAvailable]";
bindingElement.PollingStatement = "EXEC [dbo].[usp_SelectAvailableData]";
bindingElement.PollingIntervalInSeconds = 10;
var binding = new CustomBinding();
binding.Elements.Add(adapter);
var parameters = new BindingParameterCollection();
var context = new BindingContext(binding, parameters);
var credentials = new ClientCredentials();
credentials.UserName.UserName = "username";
credentials.UserName.Password = "password";
var address = (ConnectionUri) buildConnectionUri.Invoke(adapter, new []{ new Uri("mssql://azure.database.windows.net//SampleDb?InboundId=uniqueId")});
var connectionFactory = (IConnectionFactory)buildConnectionFactory.Invoke(adapter, new object[] { address, credentials, context });
var connection = connectionFactory.CreateConnection();
connection.Open(TimeSpan.MaxValue);
MetadataLookup lookup = null; // ??
var browser = connection.BuildHandler<IMetadataBrowseHandler>(lookup);
connection.Close(TimeSpan.MaxValue);
}
Ответ №1:
Отвечая на свой собственный вопрос, я понял это, просмотрев код мастера «Использовать службу адаптера». Ключ заключается в использовании IMetadataRetrievalContract
интерфейса, который внутренне реализован с использованием до трех интерфейсов LOB-SDK и, в частности IMetadataResolverHandler
.
Вот код, который работает без отражения:
var extension = new SqlAdapterBindingElementExtensionElement();
var adapter = (Adapter) Activator.CreateInstance(extension.BindingElementType);
var bindingElement = (SqlAdapterBindingElement)adapter;
bindingElement.AcceptCredentialsInUri = false;
bindingElement.InboundOperationType = InboundOperation.TypedPolling;
bindingElement.PolledDataAvailableStatement = "EXEC [dbo].[usp_IsDataAvailable]";
bindingElement.PollingStatement = "EXEC [dbo].[usp_SelectAvailableData]";
bindingElement.PollingIntervalInSeconds = 10;
var binding = new CustomBinding();
binding.Elements.Add(adapter);
const string endpoint = "mssql://azure.database.windows.net//SampleDb?InboundId=unique";
var factory = new ChannelFactory<IMetadataRetrievalContract>(binding, new EndpointAddress(new Uri(endpoint)));
factory.Credentials.UserName.UserName = "username";
factory.Credentials.UserName.Password = "password";
factory.Open();
var channel = factory.CreateChannel();
((IChannel)channel).Open();
var metadata = channel.Browse(MetadataRetrievalNode.Root.DisplayName, 0, Int32.MaxValue);
((IChannel) channel).Close();
factory.Close();