gpt4 book ai didi

c# - 使用 DynamicObject 存储类型信息

转载 作者:太空宇宙 更新时间:2023-11-03 15:48:59 25 4
gpt4 key购买 nike

我正在尝试设计一个执行提取转换加载操作的过程。我想在我的管道中使用 ExpandoObject 以允许我轻松地将列添加到我的数据流中。基本上,我从某种数据源读取数据,将其转换为动态数据,然后将其返回到转换管道,该转换管道根据现有属性或其他内容向其添加属性,然后将其流式传输到数据库中。

我遇到的问题是,即使我添加了 Nullable 类型,我也需要添加到我的 expando 对象的所有属性的类型信息。如果 Nullable 类型为 null,则由于值的装箱,这将丢失。我需要类型信息,以便在我的管道结束时我可以通过我的 ExpandoObjects 枚举实现数据读取器并将数据流式传输到数据库中。

我曾希望 SetMemberBinder.ReturnType 属性可能对我有所帮助,但它似乎返回了一个对象。

这是一些示例代码:

using System;
using System.Collections.Generic;
using System.Dynamic;

using Xunit

namespace Whanger
{
public class MyExpando : DynamicObject
{
Dictionary<string, object> properties = new Dictionary<string, object>();
Dictionary<string, Type> propertyTypes = new Dictionary<string, Type>();

public Dictionary<string, Type> Types
{
get
{
return propertyTypes;
}
}

public Dictionary<string, object> Values
{
get
{
return properties;
}
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (properties.ContainsKey(binder.Name))
{
result = properties[binder.Name];
return true;
}
else
{
result = null;
return false;
}
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
properties[binder.Name] = value;
propertyTypes[binder.Name] = binder.ReturnType;//always object :(
return true;
}

public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
dynamic method = properties[binder.Name];
result = method(args[0].ToString(), args[1].ToString());
return true;
}
}

public class MyExpandoTests
{
[Fact]
public void CanAddDynamicMembers()
{
dynamic obj = new MyExpando();
obj.Name = "Wibble";
obj.Value = 2;

Assert.Equal(obj.Name, "Wibble");
Assert.Equal(obj.Value, 2);
}

[Fact]
public void CanMaintainType()
{
dynamic obj = new MyExpando();
int? nullableInt = null;
obj.NullInt = nullableInt;
obj.Name = "Wibble";
Assert.Equal(obj.Name, "Wibble");
Assert.Null(obj.NullInt);
//fails
Assert.Equal(typeof(int?), ((MyExpando)obj).Types["NullInt"]);


}
}
}

有没有办法从 TrySetMember 中找出类型?我想知道是否有某种方法可以使用某种表达树魔法?

如果有人有任何好主意,我很乐意听取他们的意见。除了可为 null 的类型外,一切都很好,但它们是数据库操作的关键。

谢谢

最佳答案

是的,这是可能的。

我研究了类型信息是否存储在某处,我发现在设置成员期间,有一个 Func<System.Runtime.CompilerServices.CallSite,object,int?,object>正在使用的对象。这可能用于存储绑定(bind)供以后使用。

然而,这个缓存实际上是传递给binder的:private CallSiteBinder.Cache 字段。它包含一个 IDictionary<Type,object>包含作为键的缓存委托(delegate)类型和委托(delegate)本身。因此,通过检查委托(delegate)类型的泛型参数,您可以获得赋值中使用的表达式的类型。

完整方法:

private static readonly FieldInfo CallSiteBinder_Cache = typeof(CallSiteBinder).GetField("Cache", BindingFlags.NonPublic | BindingFlags.Instance);
private static Type BindingType(CallSiteBinder binder)
{
IDictionary<Type,object> cache = (IDictionary<Type,object>)CallSiteBinder_Cache.GetValue(binder);
Type ftype = cache.Select(t => t.Key).FirstOrDefault(t => t != null && t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Func<,,,>));
if(ftype == null) return null;
Type[] genargs = ftype.GetGenericArguments();
return genargs[2];
}

此方法获取 secret Cache 字典并找到一个 Type 键,该键是从 Func<T1,T2,T3,TResult> 构造的.然后只是提取类型参数。

关于c# - 使用 DynamicObject 存储类型信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26724479/

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