方法没有解决动态泛型类型 [英] Method not being resolved for dynamic generic type

查看:150
本文介绍了方法没有解决动态泛型类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这几种:

 公共类GenericDao< T> 
{
公共t保持(T T)
{
返回吨;
}
}

公共抽象类的domainObject {
//一些性质

保护抽象的动态道{搞定; }

公共虚拟无效保存(){
无功道=道;
dao.Save(本);
}
}

公共类附件:domainObject的
{
保护动态道{{返回新GenericDao<附件>(); }}
}



后来,当我运行此代码失败并RuntimeBinderException:最佳重载的方法匹配'GenericDAO<附件> .Save(附件)'有一些无效参数

  VAR OBJ =新的附件(){/ *组属性* /}; 
obj.Save();



我已经验证,在DomainObject.Save()这绝对是附件,所以错误并没有真正意义。 ?任何人都可以解释为什么该方法不解决一些轻



一些详细信息 - 如果我改变DomainObject.Save的内容()使用反射它成功:

 公共虚拟无效保存(){
无功道=道;
变种类型= dao.GetType();
VAR节约=((型)型).GetMethod(保存);
save.Invoke(DAO,新[] {此});
}


解决方案

的问题是,某些方面动态方法调用的编译时得到解决。这是由设计。从语言规范(重点煤矿):




要素表达式的7.2.3类型



当一个操作静态绑定,
的组成表达式
的类型(例如,一个接收器和参数,一个
指数或操作数)总是
认为是表达式的编译时类型
。当操作
的动态绑定,一个
组分表达的类型被确定在取决于组成
表达的
编译时类型不同的方式



•编译时类型动态的构成要素表达

认为有
实际值表达式的类型
将在运行时



•一个
组成表达式,它的
编译时类型是类型参数
被认为是有b中的类型参数在
运行时绑定到哪个$ b $类型



,否则构成
表达被认为是有它
编译时类型。




下面,组成表达这个具有编译时类型 domainObject的< INT> (简化:源代码是一个泛型类型,使复杂化应该如何意见的编译时类型这个,但我希望,我的意思理解),由于这种类型是不是动态或类型参数,<强>其类型作为其编译时类型



所以,粘结剂查找的方法保存服用类型的单个参数 domainObject的< INT> (或者它本来是合法的传递类型的对象 domainObject的< INT> 在编译时)。



这本来看上去的有些的这样的有约束力的发生在编译​​时:

  //额外的演员加入到突出误差在正确的位置。 
//(这不正是* *发生了什么。)
domainObject的< INT> O =(domainObject的< INT>)(对象),这一点;
GenericDao<&附件GT;道=(GenericDao<&附件GT;)道;

//这里编译时错误。
//强制转换是从domainObject的<企图; INT> - >附件。
dao.Save(O);



但是,这不能因为担心对的唯一候选人,工作方法GenericDao<附件> 附件保存(附件),而对于这种方法,没有隐式转换从类型参数的存在( domainObject的< INT> )的参数的类型(附件)。



所以我们获得了编译时错误:

 最好的对于重载方法匹配'GenericDao<附件> .Save(附件)'有一些无效参数
参数1:不能从转换'的domainObject< INT>'到'附件'

这个的是,被推迟到运行时使用动态版本。反思不具备同样的问题,因为它并不试图提取有关在编译时的方法调用部分的信息,不同的是动态版本。



幸运的是,该修补程序很简单,推迟组成表达式类型的评价:

  dao.Save((动态)本); 

这使我们进入选项1(编译时类型动态)。在类型组成,表达被推迟到运行时,这有助于我们绑定到正确的方法。然后代码的静态绑定相当于是一样的东西:

  //额外增加铸件得到这从一个普通的编译类型
扣押O =(附件)(对象),这一点;
GenericDao<&附件GT;道=(GenericDao<&附件GT;)道;

//没问题,就GenericDao<保存方法;附件>
//需要的附件类型的参数。
dao.Save(O);



这应该工作正常。


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});
}

解决方案

The problem is that some aspects of the dynamic method-call are resolved at compile-time. This is by design. From the language specification (emphasis mine):

7.2.3 Types of constituent expressions

When an operation is statically bound, the type of a constituent expression (e.g. a receiver, and argument, an index or an operand) is always considered to be the compile-time type of that expression. When an operation is dynamically bound, the type of a constituent expression is determined in different ways depending on the compile-time type of the constituent expression:

• A constituent expression of compile-time type dynamic is considered to have the type of the actual value that the expression evaluates to at runtime

• A constituent expression whose compile-time type is a type parameter is considered to have the type which the type parameter is bound to at runtime

Otherwise the constituent expression is considered to have its compile-time type.

Here, the constituent expression this has a compile-time type DomainObject<int> (simplification: the source-code is in a generic type, so that complicates how we should "view" the compile-time type of this, but hopefully, what I mean is understood), and since this is not of type dynamic or a type-parameter, its type is taken as its compile-time type.

So the binder looks for a method Save taking a single parameter of type DomainObject<int> (or to which it would have been legal to pass an object of type DomainObject<int> at compile-time).

It would have looked somewhat like this had the binding happened at compile-time:

// Extra casts added to highlight the error at the correct location. 
// (This isn't *exactly* what happens.)
DomainObject<int> o = (DomainObject<int>) (object)this;
GenericDao<Attachment> dao = (GenericDao<Attachment>)Dao;

// Compile-time error here. 
// A cast is attempted from DomainObject<int> -> Attachment.
dao.Save(o);

But this can't work since the only candidate-method of concern on GenericDao<Attachment> is Attachment Save(Attachment), and for this method, no implicit conversion exists from type of the argument (DomainObject<int>) to the type of the parameter (Attachment).

So we get the compile-time error:

The best overloaded method match for 'GenericDao<Attachment>.Save(Attachment)' has some invalid arguments
Argument 1: cannot convert from 'DomainObject<int>' to 'Attachment'

And this is the error that is deferred until run-time with the dynamic version. Reflection doesn't have the same problem because it doesn't attempt to extract "partial" information about the method-call at compile-time, unlike the dynamic version.

Fortunately, the fix is simple, defer the evaluation of the type of the constituent-expression:

dao.Save((dynamic)this);

This moves us into option 1 (compile-time type dynamic). The type of the constituent-expression is deferred until run-time, and this helps us bind to the right method. Then the statically-bound equivalent of the code is something like:

// Extra casts added to get this to compile from a generic type
Attachment o = (Attachment)(object)this;
GenericDao<Attachment> dao  = (GenericDao<Attachment>)Dao;

// No problem, the Save method on GenericDao<Attachment> 
// takes a single parameter of type Attachment.
dao.Save(o); 

which should work fine.

这篇关于方法没有解决动态泛型类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆