【问题标题】:Specify Web Service Reference Auto-Generated Entity base class指定 Web 服务引用自动生成的实体基类
【发布时间】:2009-09-30 13:27:46
【问题描述】:

问题:
是否可以(自动)更改通过 Visual Studio 的“添加 Web 引用”功能创建的自动生成域对象的基类,而无需手动修改 References.cs?

背景:
当我们添加对 Web 服务的引用时(通过 Visual Studio 的“添加 Web 引用”功能),会自动生成许多类。这些代表一个代理对象(例如 MyServiceSoapClient)和一些自动生成的域对象(例如 CustomerInfo)。

所以,如果我按照以下方式做一些事情:

MyServiceSoapClient client = new MyServiceSoapClient();
CustomerInfo cust = client.GetCustomer("John Smith");

我将取回一个带有各种属性等的 CustomerInfo 对象,所有这些都很好地从服务器返回的任何 XML 中反序列化。

问题是......
假设我将 cust 对象中 Name 属性的值更改为“Bob Dylan”。
理想情况下,我希望有一个名为 ServiceEntity 的基类,它将跟踪是否进行了更改(通过在基类中捕获大陆提供的 INotifyPropertyChanged.PropertyChanged 事件),以提供指示对象具有的“脏”属性由于它是从服务中获取的,因此发生了变化。

解决方案
虽然下面的答案是一个很好的答案,但我们采取了一种略有不同的方法......
由于同步状态只需要在少数情况下记录,因此通过 Generic 类添加同步跟踪更有意义,因此我们可以在需要时使用它。
这是一个通用类和接口的示例:

界面:

public interface ISyncEntity
{
    /// <summary>
    /// Gets or Sets the Entity Sync State
    /// </summary>
    [XmlIgnore]
    [SoapIgnore]
    EntitySyncState SyncState { get; set; }

    /// <summary>
    /// Flag for deletion
    /// </summary>
    void DeleteOnSync();

    /// <summary>
    /// Flag for Creation
    /// </summary>
    void CreateOnSync();
}

类:

public class SyncEntity<TEntity> : ISyncEntity
{
    /// <summary>
    /// Backing Field for Entity Property
    /// </summary>
    private TEntity _entity;

    /// <summary>
    /// Gets or Sets the Entity in question
    /// </summary>
    public TEntity Entity
    {
        get { return _entity; }
        set { OnEntityChange(value); }
    }

    /// <summary>
    /// Invoked when a Property on the Entity is changing
    /// </summary>
    /// <param name="entity"></param>
    protected void OnEntityChange(TEntity entity)
    {
        // Detach the property change event handler from the previous entity?
        if (_entity is INotifyPropertyChanged)
            (entity as INotifyPropertyChanged).PropertyChanged -= OnPropertyChange;

        // Set backing field
        _entity = entity;

        // Implements INotifyPropertyChanged?
        if (entity is INotifyPropertyChanged)
            (entity as INotifyPropertyChanged).PropertyChanged += OnPropertyChange;

        // Set the Sync State
        SyncState = EntitySyncState.Unchanged;
    }



    /// <summary>
    /// Fired when a property in the entity changes
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void OnPropertyChange(object sender, PropertyChangedEventArgs e)
    {
        // If a delete or create is already pending, don't worry about the update!
        if (SyncState == EntitySyncState.Unchanged)
            SyncState = EntitySyncState.UpdatePending;
    }

    #region Sync Framework Members

    [XmlIgnore]
    [SoapIgnore]
    public EntitySyncState SyncState
    {
        get;
        set;
    }

    public void DeleteOnSync()
    {
        SyncState = EntitySyncState.DeletePending;
    }

    public void CreateOnSync()
    {
        SyncState = EntitySyncState.CreatePending;
    }

    #endregion
}

扩展方法:

public static SyncEntity<TEntity> ToSyncEntity<TEntity>(this TEntity source)
{
    if (source == null)
        throw new ArgumentException("Source cannot be null");

    return new SyncEntity<TEntity>()
    {
        Entity = source
    };
}

【问题讨论】:

  • 但您不必编辑标题即可说它已解决,选择一个答案就足够了,并且可以让人们更轻松地搜索

标签: c# visual-studio-2008 web-services auto-generate


【解决方案1】:

通过 Visual Studio 的 Web 引用功能生成的客户端代理类是使用 .Net Framework 的 wsdl.exe utility 构建的。生成时,输出会生成公共部分类。您可以在另一个文件中提供额外的类代码,而不是尝试修改自动生成的输出,以添加您尝试实现的事件代码。

当然,剩下的就是为每个对象实现类似的代码。根据您的源服务,您可以考虑扩展SoapHttpClientProtocol(或代表您的对象的任何协议基类)以为您的所有继承对象提供单一实现。如果不使用AOP,这可能是不可能的。因此,您的里程可能会有所不同。

【讨论】:

  • 这实际上是一个非常好的主意。然而,我们通过实现对 PropertyChanged 事件(来自 INotifyPropertyChanged 接口)做出反应的基于泛型的类和创建 SyncObject 的泛型扩展方法解决了这个问题。这还有一个额外的好处,那就是让我们的代码保持整洁,并且只有在我们明确需要时才以监控同步数据为代价。感谢您的帮助!
  • 泛型来拯救!我更喜欢这种策略。有效地包装 EF 类可能是一个挑战。
  • 我已经准备好尝试这个,但它对我不起作用,因为生成的类显式继承自对象,所以虽然你可以扩展类,但你不能提供一个不同的基类,这是原始问题提出的(以及我需要做的)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多