调用Silverlight Ria服务设计问题

发布于 2024-12-14 01:26:19 字数 441 浏览 6 评论 0原文

我正在尝试创建一个调用 Ria WebServices 的 silverlight 应用程序,问题是我不想将(紧密耦合)Ria 服务连接到我的 ViewModel 中。

我的想法是创建一个接口包装器。例如,如果我想使用 Ria 身份验证服务,我只需创建自己的身份验证服务

public interface IMyAuthenticationService
 {
   void Login();
   void LoginCallBack(LoginResult result);
   event MyHandler LoginComplete()
 }

,然后就可以在我的视图模型中为任何身份验证服务使用上述接口的实现。这有望减少与 Ria 服务的耦合,因为上述接口是通用的。

我想知道您是否能为我提供有关上述想法的任何反馈。我不确定这是否是解决这种情况的好方法。

I am trying to create a silverlight app that calls Ria WebServices, The Problem is i do not want Wire in (tightly couple) Ria Services into my ViewModel.

My idea was to Creata an interface wrapper. For example, if i wanted to use Ria Authentication Services i would simply create my own

public interface IMyAuthenticationService
 {
   void Login();
   void LoginCallBack(LoginResult result);
   event MyHandler LoginComplete()
 }

I could then use an implementation of the above interface in my viewmodel, for any Authentication Service. This would hopefully reduce the coupling to Ria services, since the above interface is generic.

I was wondering if you could provide me with any feedback on the above idea. I'm not sure if this is a good way to approach the situation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

送君千里 2024-12-21 01:26:19

我建议您构建一个紧密耦合的模型层以与 RIA 服务一起使用。如果模型层能够通过 RIA 完成所需的所有工作(它应该是可独立测试的),那么您可以开始使用您建议的界面通过视图模型转换这些操作;您可以在单独的 Silverlight 库中构建模型层。

我使用 TDD 通过企业解决方案成功地做到了这一点。如果需要,我可以提供更具体的代码示例,但即使是简单的服务调用也会有很多类。我可以添加一些代码示例。

例如,从底部(服务)到顶部(视图):

我们从非常复杂的 MultiplyService 开始:

namespace StackOverflow.Tutorial.Web
{
    using System;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;

    [EnableClientAccess()]
    public class MultiplyService : DomainService
    {
        [Invoke]
        public MultiplyDTO Multiply(MultiplyDTO input)
        {
            input.Answer = input.A * input.B;
            return input;
        }

        public class MultiplyDTO
        {
            public int Answer { get; set; }
            public int A { get; set; }
            public int B { get; set; }
        }
    }
}

它通过 MultiplyContext 类向我们的 Silverlight 客户端公开一些 RIA 魔法。我们在模型中的 silverlight 端使用此类:

using System;
using StackOverflow.Tutorial.Web;
using System.ServiceModel.DomainServices.Client;

namespace StackOverflow.Tutorial.Models
{
    // This class is tightly coupled to 
    public class MultiplyServiceAgent : IMultiplyServiceAgent
    {
        public void Multiply(int a, int b, Action<int> callback)
        {
            MultiplyContext context = new MultiplyContext();
            MultiplyDTO question = new MultiplyDTO() { A = a, B = b };

            context.Multiply(question, (answer) =>
            {
                callback(answer.Value.Answer);
            }, null);
        }
    }
}

我还包含一个接口 IMultiplyServiceAgent:

using System;
using System.ServiceModel.DomainServices.Client;
using StackOverflow.Tutorial.Web;

namespace StackOverflow.Tutorial.Models
{
    public interface IMultiplyServiceAgent
    {
        void Multiply(int a, int b, Action<int> callback);
    }
}

如果需要,服务代理和接口可以编译成单独的类库,然后由视图使用silverlight 应用程序的模型和视图,如下所示。首先是 ViewModel:

using System;
using System.Net;
using System.Windows;
using StackOverflow.Tutorial.Models;

namespace StackOverflow.Tutorial.ViewModels
{
    public class MultiplyViewModel : DependencyObject
    {
        IMultiplyServiceAgent agent = new MultiplyServiceAgent();

        public int A
        {
            get { return (int)GetValue(AProperty); }
            set { SetValue(AProperty, value); }
        }

        // Using a DependencyProperty as the backing store for A.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AProperty =
            DependencyProperty.Register("A", typeof(int), typeof(MultiplyViewModel), new PropertyMetadata(0));

        public int B
        {
            get { return (int)GetValue(BProperty); }
            set { SetValue(BProperty, value); }
        }

        // Using a DependencyProperty as the backing store for B.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BProperty =
            DependencyProperty.Register("B", typeof(int), typeof(MultiplyViewModel), new PropertyMetadata(0));

        public int Answer
        {
            get { return (int)GetValue(AnswerProperty); }
            set { SetValue(AnswerProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Answer.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AnswerProperty =
            DependencyProperty.Register("Answer", typeof(int), typeof(MultiplyViewModel), new PropertyMetadata(0));

        public void Calculate()
        {
            agent.Multiply(this.A, this.B, (answer) =>
                {
                    this.Answer = answer;
                });
        }
    }
}

最后是视图:

<UserControl x:Class="StackOverflow.Tutorial.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <StackPanel x:Name="LayoutRoot" Background="White">
        <TextBox Name="txtA" Text="{Binding A, Mode=TwoWay}" />
        <TextBox Name="txtB" Text="{Binding B, Mode=TwoWay}" />
        <Button Name="btnCalculate" Content="Calculate" Click="btnCalculate_Click" />
        <TextBlock Name="txtAnswer" Text="{Binding Answer}" />
    </StackPanel>
</UserControl>

视图背后有一个简单的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using StackOverflow.Tutorial.ViewModels;

namespace StackOverflow.Tutorial.Views
{
    public partial class MainPage : UserControl
    {
        public MultiplyViewModel ViewModel { get; set; }
        public MainPage()
        {
            InitializeComponent();
            this.ViewModel = new MultiplyViewModel();
            this.DataContext = this.ViewModel;
        }

        private void btnCalculate_Click(object sender, RoutedEventArgs e)
        {
            this.ViewModel.Calculate();
        }
    }
}

所以我们在上面的示例中看到,silverlight 应用程序的 Web 服务和模型是紧密耦合和集成的。具有 ServiceAgent 和 IService 接口的模型可以在其自己的 Silverlight 类库中构建,并与企业解决方案中的各种 Silverlight 应用程序共享。由于 RIA 确实要求提供者和消费者紧密耦合,因此限制这种依赖性将防止将来出现问题,正如您在问题中指出的那样。

现在提供者和使用者已准备就绪,主 Silverlight 应用程序通过 ViewModel 将模型连接到视图。 (ViewModel 和 View 通常也是紧密耦合的)。

I would suggest that you build a tightly coupled Models layer for use with your RIA services. If the Model layer is able to do all the work required through RIA, (it should be independantly testable) Then you can begin translating those operations through your View Model using an interface like you suggested; you could build the Models layer in a seperate Silverlight Library.

I successfully did exactly this with an enterprise solution, using TDD. I can provide more concrete code examples, if needed, but even a simple service call would have lots of classes. I can add some code samples.

Example, from the Bottom (the service) to the Top (the View):

We start with our very complex MultiplyService:

namespace StackOverflow.Tutorial.Web
{
    using System;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;

    [EnableClientAccess()]
    public class MultiplyService : DomainService
    {
        [Invoke]
        public MultiplyDTO Multiply(MultiplyDTO input)
        {
            input.Answer = input.A * input.B;
            return input;
        }

        public class MultiplyDTO
        {
            public int Answer { get; set; }
            public int A { get; set; }
            public int B { get; set; }
        }
    }
}

Which exposes some RIA magic to our Silverlight Client through a MultiplyContext class. We consume this class on the silverlight side in the Model thus:

using System;
using StackOverflow.Tutorial.Web;
using System.ServiceModel.DomainServices.Client;

namespace StackOverflow.Tutorial.Models
{
    // This class is tightly coupled to 
    public class MultiplyServiceAgent : IMultiplyServiceAgent
    {
        public void Multiply(int a, int b, Action<int> callback)
        {
            MultiplyContext context = new MultiplyContext();
            MultiplyDTO question = new MultiplyDTO() { A = a, B = b };

            context.Multiply(question, (answer) =>
            {
                callback(answer.Value.Answer);
            }, null);
        }
    }
}

I aslo include an interface IMultiplyServiceAgent:

using System;
using System.ServiceModel.DomainServices.Client;
using StackOverflow.Tutorial.Web;

namespace StackOverflow.Tutorial.Models
{
    public interface IMultiplyServiceAgent
    {
        void Multiply(int a, int b, Action<int> callback);
    }
}

The Service Agent and Interface could be compiled into a seperate class library, if you wanted, then used by the View Model and View of your silverlight app, which are shown next. First the ViewModel:

using System;
using System.Net;
using System.Windows;
using StackOverflow.Tutorial.Models;

namespace StackOverflow.Tutorial.ViewModels
{
    public class MultiplyViewModel : DependencyObject
    {
        IMultiplyServiceAgent agent = new MultiplyServiceAgent();

        public int A
        {
            get { return (int)GetValue(AProperty); }
            set { SetValue(AProperty, value); }
        }

        // Using a DependencyProperty as the backing store for A.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AProperty =
            DependencyProperty.Register("A", typeof(int), typeof(MultiplyViewModel), new PropertyMetadata(0));

        public int B
        {
            get { return (int)GetValue(BProperty); }
            set { SetValue(BProperty, value); }
        }

        // Using a DependencyProperty as the backing store for B.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BProperty =
            DependencyProperty.Register("B", typeof(int), typeof(MultiplyViewModel), new PropertyMetadata(0));

        public int Answer
        {
            get { return (int)GetValue(AnswerProperty); }
            set { SetValue(AnswerProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Answer.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AnswerProperty =
            DependencyProperty.Register("Answer", typeof(int), typeof(MultiplyViewModel), new PropertyMetadata(0));

        public void Calculate()
        {
            agent.Multiply(this.A, this.B, (answer) =>
                {
                    this.Answer = answer;
                });
        }
    }
}

And finally, the View:

<UserControl x:Class="StackOverflow.Tutorial.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <StackPanel x:Name="LayoutRoot" Background="White">
        <TextBox Name="txtA" Text="{Binding A, Mode=TwoWay}" />
        <TextBox Name="txtB" Text="{Binding B, Mode=TwoWay}" />
        <Button Name="btnCalculate" Content="Calculate" Click="btnCalculate_Click" />
        <TextBlock Name="txtAnswer" Text="{Binding Answer}" />
    </StackPanel>
</UserControl>

The View has a simple code behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using StackOverflow.Tutorial.ViewModels;

namespace StackOverflow.Tutorial.Views
{
    public partial class MainPage : UserControl
    {
        public MultiplyViewModel ViewModel { get; set; }
        public MainPage()
        {
            InitializeComponent();
            this.ViewModel = new MultiplyViewModel();
            this.DataContext = this.ViewModel;
        }

        private void btnCalculate_Click(object sender, RoutedEventArgs e)
        {
            this.ViewModel.Calculate();
        }
    }
}

So we see, in the examples above, that the Web Service and the Model of the silverlight app are tightly coupled, and integrated. The Model - with the ServiceAgent(s) and IService interfaces could be built in its own Silverlight Class Library, and shared with the various Silverlight apps in your enterprise solution. Since RIA really requires that the provider, and consumer be so tightly coupled, limiting this dependancy will prevent problems in the future, as you pointed out in the question.

Now that the provider and consumer are ready, the main Silverlight app wires up the Model through the ViewModel to the View. (ViewModels and Views are also tightly coupled, usually).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文