Seb*_*son 1 c# dynamic anonymous-types
如何在对象内部公开匿名对象的复杂结构dynamic?
匿名对象被标记为internal,所以我正在寻找一种创造性的方法来解决这个问题.
// This is the library I control
public void SendObject() {
var anonymous = new {
Text = "Test",
SubItem = new {
SubText = "Bla",
SubSub = new {
SubSubText = "Baha"
}
}
};
}
dynamic dyn = ExposeAnonymous(anonymous); // Perform voodoo
var result = ExternalLibrary.GetSpecialProperty(dyn);
// External library I don't control
public object GetSpecialProperty(dynamic dyn) {
return dyn.SubItem.SubSub.SubSubText;
}
Run Code Online (Sandbox Code Playgroud)
问题是当发送dynamic到我无法控制的其他外部库时,会出现如下错误:
'object'不包含'SubItem'的定义.
问题是将动态发送到其他库时,
......而且还有一个问题.匿名类型internal由C#编译器声明,这意味着其他程序集无权访问它们.
要么停止使用匿名类型,要么使用[InternalsVisibleToAttribute]该类型使其他程序集可见.在包含创建匿名类型实例的类型的程序集中,使用:
[InternalsVisibleTo("ExternalLibrary")]
Run Code Online (Sandbox Code Playgroud)
(我实际上期待这个问题SubItem不是SubSub......)
匿名类型是internal,并且DLR在编译时在编译时执行的运行时进行相同的可访问性分析.因此,您无法使用其他程序集访问匿名类型的成员dynamic.
一种选择可能是使用ExpandoObject:
dynamic a = new ExpandoObject();
a.Text = "Test";
a.SubItem = new ExpandoObject();
a.SubItem.SubText = "Blah";
a.SubItem.SubSub = new ExpandoObject();
a.SubItem.SubSub.Text = "Baha";
Run Code Online (Sandbox Code Playgroud)
这有点难看,你可以保持匿名类型并使用辅助方法递归转换为ExpandoObject:
public static dynamic ConvertToExpando(object obj)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach(var pi in obj.GetType().GetProperties())
{
// there doesn't seem to be a way to know if it is an anonymous type directly. So I use IsPublic here.
if (pi.PropertyType.IsPublic)
{
expando[pi.Name] = pi.GetValue(obj);
}
else
{
expando[pi.Name] = ConvertToExpando(pi.GetValue(obj));
}
}
return expando;
}
Run Code Online (Sandbox Code Playgroud)
这就是你需要的"执行伏都教".