c#确认实现接口后访问实体的属性

时间:2012-11-01 13:16:33

标签: c# generics interface poco

我需要在某些操作上更新我的POCO实体的某些属性。

我定义了以下接口:

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实现了很多不同的属性(都具有相应的接口),因此使用不同的函数签名来解决问题几乎是不可能的。
  • 出于性能原因,我宁愿不使用反射。

有没有可行的办法让我摆脱痛苦?

3 个答案:

答案 0 :(得分:4)

你需要更多()投射:

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

因为有很多不同的属性

然后它将很快支付使用temp var:

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

答案 1 :(得分: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;
        }
    }
}

答案 2 :(得分:1)

你需要施放。

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

或者

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