Обходной путь для ограничения общих атрибутов С#

Как обсуждалось здесь, С# не поддерживает объявление общего атрибута. Поэтому мне не разрешено делать что-то вроде:

[Audit<User> (UserAction.Update)]
public ActionResult SomeMethod(int id){ ...

который поместился бы как очарование в моем классе атрибута impl, потому что мне нужно вызвать метод из общего репозитория:

User fuuObj = (User) repository.LoadById<T>(_id);

Я попытался использовать это решение без успеха. Я могу передать что-то вроде typeOf(User), но как я могу вызвать LoadById только с типом или магической строкой?

* Оба, T и User, расширяют базовый класс Entity.

Ответ 1

Вы можете использовать отражение для загрузки по id:

public class AuditAttribute : Attribute
{
    public AuditAttribute(Type t)
    {
        this.Type = t;
    }

    public  Type Type { get; set; }

    public void DoSomething()
    {
        //type is not Entity
        if (!typeof(Entity).IsAssignableFrom(Type))
            throw new Exception();

        int _id;

        IRepository myRepository = new Repository();
        MethodInfo loadByIdMethod =  myRepository.GetType().GetMethod("LoadById");
        MethodInfo methodWithTypeArgument = loadByIdMethod.MakeGenericMethod(this.Type);
        Entity myEntity = (Entity)methodWithTypeArgument.Invoke(myRepository, new object[] { _id });
    }
}

Ответ 2

У вас есть как минимум три возможности:

  • Вы можете использовать отражение для вызова LoadById
  • Вы можете создать дерево выражений, которое вызывает LoadById
  • Вы можете предоставить метод LoadById в вашем репозитории, который не является общим.