2009-09-30 68 views
1

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

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

所以,如果我做沿着以下线的东西:

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

我会回来一个CustomerInfo对象具有各种属性等,均能从任何XML服务器返回的反序列化。

问题是...
可以说,我更改卡斯特对象为“鲍勃·迪伦”的名称属性的值。
理想情况下,我想有一个名为ServiceEntity的基类,它将跟踪是否进行了更改(通过捕获基本类中提供的Continently提供的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 
    }; 
} 
+0

丹你不必编辑标题说它已经解决了,选择一个答案就足够了,让人们更容易搜索 – blowdart

回答

1

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

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

+0

这实际上是一个非常好的主意。 然而,我们通过实现对PropertyChanged事件(来自INotifyPropertyChanged接口)和泛型扩展方法作出反应的基于泛型的类来创建SyncObject 来解决此问题。 这还带来了额外的好处,可以让我们保持代码的清洁和干净,并且只在我们明确需要时监控同步数据。 感谢您的帮助! – Dan

+0

通用救援!我更喜欢这个策略。有效地包装EF课程可能是一个挑战。 – jro

+0

我都试过这样做,但它不适用于我,因为生成的类*显式*从对象继承,所以虽然可以扩展类,但不能提供不同的基类,这是原始问题问(以及我需要做什么)。 –

相关问题