2012-11-01 15 views
0

我需要在某些動作上更新我的POCO實體的某些屬性。c#在確定它實現了一個接口後訪問一個實體的屬性

我定義了以下接口:

public interface IEntityPOCO 
{ 
    Guid Id { get; set; } 
} 

public interface IHasLastChange : IEntityPOCO 
{ 
    DateTime LastChange { get; set; } 
} 

下面是一個例子操作方法:

public void SomeStuff<T>(T entity) where T : class, IEntityPOCO 
{ 
    entity.Id = Guid.NewGuid(); // Works like a charm. 

    if (entity is IHasLastChange) 
    { 
     entity.LastChange = DateTime.Now; // Doesn't work. D'oh. 
     (IHasLastChange)entity.LastChange = DateTime.Now; // Doesn't work either. 
    } 
} 
  • 因爲有相當多的可能實現不同的屬性(所有帶相應的接口)的由POCO開展的關於不同功能簽名的問題幾乎沒有問題。
  • 我寧可不使用反射性能的原因。

有沒有什麼可行的方法讓我擺脫不幸?

回答

4

您需要在鑄造更()

// (IHasLastChange)entity.LastChange = DateTime.Now; 
    ((IHasLastChange)entity).LastChange = DateTime.Now; 

因爲有相當多的不同性質

然後,它會很快支付使用一個臨時變種:

if (entity is IHasLastChange) 
{ 
    lastChange = (IHasLastChange) entity; 
    lastChange.LastChange = DateTime.Now; 
    lastChange. ... 
} 
1

您需要投射。

var hasLastChange = entity as IHasLastChange; 
hasLastChange.LastChange = DateTime.Now; //It works! 

或者

((IHasLastChange)entity).LastChange = DateTime.Now; //It also works! 
2

常見的方式做,這將是與as投實體,並檢查它是否null,就像這樣:

var lastChangedEntity = entity as IHasLastChange; 
if (lastChangedEntity != null) 
{ 
    lastChangedEntity.LastChange = DateTime.Now; 
} 

但是,這導致隨着不同接口數量的增加,令人討厭的代碼氣味。

如果是這種情況,請考慮使用Strategy Pattern來處理它,這樣您將堅持Open/Closed Principle (OCP)並使您的應用程序更易於維護。

編輯:甲策略模式的例子是:

public void SomeStuff<T>(T entity) where T : class, IEntityPOCO 
{ 
    entity.Id = Guid.NewGuid(); // Works like a charm. 

    // _processors is a List<IProcessEntities> 
    var processors = _processors.Where(p => p.CanProcess(entity)); 

    foreach (var processor in processors) 
    { 
     processor.Process(entity); 
    } 
} 

public interface IProcessEntities 
{ 
    bool CanProcess<T>(T entity) where T : class, IEntityPOCO; 

    void Process<T>(T entity) where T : class, IEntityPOCO; 
} 

public class LastChangedProcessor : IProcessEntities 
{ 
    public bool CanProcess<T>(T entity) where T : class, IEntityPOCO 
    { 
     return typeof(IHasLastChange).IsAssignableFrom(typeof(T)); 
    } 

    public void Process<T>(T entity) where T : class, IEntityPOCO 
    { 
     var lastChangeEntity = entity as IHasLastChange; 
     if (lastChangeEntity != null) 
     { 
      lastChangeEntity.LastChange = DateTime.Now; 
     } 
    } 
}