15

As discussed here, C# doesn't support generic attribute declaration. So, I'm not allowed to do something like:

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

that would fit like a charm in my attribute impl class, cause I need to call a method from a generic repository:

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

I tried to use this solution without success. I can pass something like typeOf(User), but how can I call LoadById just with type or magic string?

*Both, T and User, extend a base class called Entity.

Community
  • 1
  • 1
Custodio
  • 8,126
  • 15
  • 79
  • 113

3 Answers3

17

You could use reflection to load by 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 });
    }
}
Bas
  • 26,014
  • 8
  • 49
  • 85
4

You have at least these three possibilities:

  1. You could use reflection to call LoadById
  2. You could create an expression tree that calls LoadById
  3. You could provide a LoadById method in your repository that is not generic.
Daniel Hilgarth
  • 166,158
  • 40
  • 312
  • 426
1

You could use reflection to invoke the LoadById method. The following msdn article should point you in the right direction:

http://msdn.microsoft.com/en-us/library/b8ytshk6(v=vs.100).aspx

Kev
  • 1,732
  • 18
  • 23