gpt4 book ai didi

c# - DynamicObject 绑定(bind) WRT 私有(private)类型

转载 作者:行者123 更新时间:2023-11-30 22:36:09 24 4
gpt4 key购买 nike

考虑以下几点:

using System;
using System.Dynamic;

namespace DynamicTest
{
class Program
{
static void Main(string[] args)
{
dynamic d = new DynamicTest();
var v = d.foo();
Console.WriteLine(v.Value);

Console.ReadKey();
}
}

public interface IValueProvider<T>
{
T Value
{
get;
}
}

public class DynamicTest : DynamicObject
{
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
result = new ValueProvider<int>(32);
return true;
}

private class ValueProvider<T> : IValueProvider<T>
{
public ValueProvider(T t)
{
this.Value = t;
}

public T Value
{
get;
private set;
}
}
}
}

这在运行时失败了:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException was unhandled
Message='object' does not contain a definition for 'Value'
Source=Anonymously Hosted DynamicMethods Assembly
StackTrace:
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at DynamicTest.Program.Main(String[] args)
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:

如果我更改 ValueProvider<T>类别为 public而不是 private它按预期工作:

// this allows it to work
public class ValueProvider<T> : IValueProvider<T>

或者,相反,如果我将结果转换为 IValueProvider<int>它也有效:

// this also allows it to work
dynamic d = new DynamicTest();
var v = (IValueProvider<int>)d.foo();

如果我尝试在 TryInvokeMember 中使用接口(interface)作为编译时类型,它不起作用(我真的没想到它会起作用,但我想我会试试):

// this doesn't help
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var valueProvider = (IValueProvider<int>)new ValueProvider<int>(32);
result = valueProvider;
return true;
}

谁能指出我在这里遗漏了什么?有没有一种方法可以让我在不公开我的所有类型且不强制转换的情况下使上面的代码正常工作?

最佳答案

有趣的是,如果可访问性是 internal,它会起作用:

internal class ValueProvider<T> : IValueProvider<T> { ... }

Hassan 指出(评论)是有道理的,因为这是 Program 使用 DynamicTest 的 API 成员通常需要的可访问性(在相同的集会)。如果我们将 Main 移动到 DynamicTest 并将其保留为 private,它会再次工作,这是我们应该期望的正确可访问性。

现在可以使用 internal

当然,这里更好的方法是只使用接口(interface)。在我看来,您在这里不需要 dynamic;您可能需要的是一个非通用的 IValueProvider:

public interface IValueProvider
{
object Value { get; }
}
public interface IValueProvider<T> : IValueProvider
{
new T Value{get; }
}

与(在类里面):

object IValueProvider.Value { get { return Value; } }

和:

var v = (IValueProvider)d.foo();
Console.WriteLine(v.Value);

关于c# - DynamicObject 绑定(bind) WRT 私有(private)类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7145029/

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