Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method not being resolved for dynamic generic type

I have these types:

public class GenericDao<T>
{
    public T Save(T t)
    {            
        return t;
    }
}

public abstract class DomainObject {
    // Some properties

    protected abstract dynamic Dao { get; }

    public virtual void Save() {
        var dao = Dao;
        dao.Save(this);
    }
}

public class Attachment : DomainObject
{
    protected dynamic Dao { get { return new GenericDao<Attachment>(); } }
}

Then when I run this code it fails with RuntimeBinderException: Best overloaded method match for 'GenericDAO<Attachment>.Save(Attachment)' has some invalid arguments

var obj = new Attachment() { /* set properties */ };
obj.Save();

I've verified that in DomainObject.Save() "this" is definitely Attachment, so the error doesn't really make sense. Can anyone shed some light on why the method isn't resolving?

Some more information - It succeeds if I change the contents of DomainObject.Save() to use reflection:

public virtual void Save() {
    var dao = Dao;
    var type = dao.GetType();
    var save = ((Type)type).GetMethod("Save");
    save.Invoke(dao, new []{this});
}
like image 933
kelloti Avatar asked Jan 12 '11 22:01

kelloti


1 Answers

Quite good answers here already. I ran into the same problem. You're right reflection does work. Because you are specifying the type by saying GetType() which gets resolved at runtime.

var method = ((object)this).GetType().GetMethod("Apply", new Type[] { @event.GetType() }); //Find the right method
            method.Invoke(this, new object[] { @event }); //invoke with the event as argument

Or we can use dynamics as follows

    dynamic d = this;
    dynamic e = @event;
    d.Apply(e);

So in your case

public abstract class DomainObject {
    // Some properties

    protected abstract dynamic Dao { get; }

    public virtual void Save() {
        var dao = Dao;
        dynamic d = this; //Forces type for Save() to be resolved at runtime
        dao.Save(d);
    }
}

This should work.

like image 113
Dasith Wijes Avatar answered Sep 28 '22 03:09

Dasith Wijes