gpt4 book ai didi

c# - 类型转换动态对象并传递到 UnitOfWork 和存储库模式。抛出异常

转载 作者:太空狗 更新时间:2023-10-29 20:26:51 24 4
gpt4 key购买 nike

这是一个非常具体的问题。不太确定怎么说。基本上我正在实现工作单元和存储库模式,我有一个动态对象,我将其转换为一个 int,但如果我使用 var,它会在尝试调用该方法时抛出异常。

我试图尽可能地删除这个问题的所有微不足道的变量。出于某种原因,我只看到这两种设计模式会发生这种情况。我得到的异常是 Additional information: 'BlackMagic.ITacoRepo' does not contain a definition for 'DoStuff'

代码如下:

class BlackMagic
{
static void Main(string[] args)
{
dynamic obj = new ExpandoObject();
obj.I = 69;

UnitOfWork uow = new UnitOfWork();

int i1 = Convert.ToInt32(obj.I);
var i2 = Convert.ToInt32(obj.I);

if(i1.Equals(i2))
{
uow.TacoRepo.DoStuff(i1); // Works fine
uow.TacoRepo.DoStuff(i2); // Throws Exception
}
}
}

class UnitOfWork
{
public ITacoRepo TacoRepo { get; set; }

public UnitOfWork()
{
TacoRepo = new TacoRepo();
}
}

class Repo<T> : IRepo<T> where T : class
{
public void DoStuff(int i)
{
}
}

interface IRepo<T> where T : class
{
void DoStuff(int i);
}

class TacoRepo : Repo<Taco>, ITacoRepo
{
}

interface ITacoRepo : IRepo<Taco>
{
}

class Taco
{
}

编辑: 我试图找到答案的主要问题是,为什么在工作单元内调用 DoStuff 会抛出异常(同时使用repo) 但如果 DoStuff 存在于 BlackMagic 类中则不会被抛出。

最佳答案

这是我 5 多年前向 Microsoft 报告的错误之一,在 dynamic 引入后不久。据我所知,它在他们的列表中被认为是一个非常低的优先级,并且可能永远不会被修复。

以下是简单的重现步骤:

using System.Collections;

class C
{
static void Main()
{
object[] array = { };
IList list = new ArrayList();
list.CopyTo(array, 0); // Works okay
dynamic index = 0;
list.CopyTo(array, index); // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.Collections.IList' does not contain a definition for 'CopyTo'
}
}

这里是问题的解释。当在静态类型为接口(interface)类型的表达式上调用函数成员(方法或索引器)时,调用的至少一个参数是 dynamic 类型(这意味着完整的成员查找——类型推断——重载解析过程被推迟到运行时,并成为运行时绑定(bind)器而不是编译器的责任;编译器仅根据不完整的类型信息执行部分检查),以及被调用的成员由接口(interface)从其基接口(interface)之一继承(而不是在接口(interface)本身中声明),然后运行时绑定(bind)程序无法正确遍历基接口(interface)树以找到继承的成员,并在运行时抛出异常,报告找不到所需的成员。请注意,这只是运行时绑定(bind)器的错误——编译器正确地接受了调用(但会拒绝它,例如,如果您在方法名称中输入错误)。

可能的解决方法:将您调用成员的表达式强制转换为实际声明您尝试调用的成员的基本接口(interface)。例如,上述重现步骤中的程序可以修复如下:

using System.Collections;

class C
{
static void Main()
{
object[] array = { };
IList list = new ArrayList();
list.CopyTo(array, 0); // Works okay
dynamic index = 0;
((ICollection) list).CopyTo(array, index); // Works okay
}
}

或者,如果可能的话,通过将 dynamic 类型的参数转换为被调用成员签名中指定的类型来完全摆脱动态分派(dispatch)。

using System.Collections;

class C
{
static void Main()
{
object[] array = { };
IList list = new ArrayList();
list.CopyTo(array, 0); // Works okay
dynamic index = 0;
list.CopyTo(array, (int) index); // Works okay
}
}

不幸的是,如果您真的希望在运行时进行重载解析,那么这两种解决方法都可能没有帮助,并且在可能的候选者中,既有接口(interface)声明的成员,也有接口(interface)继承的成员。在这种情况下,您可能需要发明一些临时解决方案,或者显着重构您的程序。

关于c# - 类型转换动态对象并传递到 UnitOfWork 和存储库模式。抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40184417/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com