0

特定のアクションで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によって実装される可能性のあるさまざまなプロパティ(すべて対応するインターフェイスを備えたもの)が非常に多いため、さまざまな関数シグネチャで問題を解決することはほとんど問題外です。
  • パフォーマンス上の理由から、リフレクションは使用しません。

私の悲惨さから私を追い出すための実行可能な方法はありますか?

4

3 に答える 3

4

()キャスティングにはもっと必要です:

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

かなりたくさんの異なるプロパティがあるので

次に、一時変数を使用することですぐに支払いが行われます。

if (entity is IHasLastChange)
{
    lastChange = (IHasLastChange) entity;
    lastChange.LastChange = DateTime.Now; 
    lastChange. ... 
}
于 2012-11-01T13:20:11.220 に答える
2

The common way to do this would be to cast the entity with as and check if it's null, like this:

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

But this leads to a nasty code smell as the number of different interfaces increase.

If this is the case, consider using the Strategy Pattern to handle it, in that way you will adhere to the Open/Closed Principle (OCP) and make your application more maintainable.

EDIT: A Strategy Pattern example would be:

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;
        }
    }
}
于 2012-11-01T13:26:36.057 に答える
1

キャストする必要があります。

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

または

((IHasLastChange)entity).LastChange = DateTime.Now; //It also works!
于 2012-11-01T13:20:24.290 に答える