C# 如何编写支持对象初始值设定项的自定义DynamicObject类
在的文档中,有一个C# 如何编写支持对象初始值设定项的自定义DynamicObject类,c#,linq,dynamic,object-initializers,C#,Linq,Dynamic,Object Initializers,在的文档中,有一个DynamicDictionary示例,它允许您使用字典,就像它是一个具有属性的类一样 以下是课程(为简洁起见稍作修改): 问题 这可能吗 如果是,如何进行 DynamicObject提供了,这是针对这种情况的,但在C#中不可用 我看到了一些解决方法: 创建一个动态工厂类。当您使用命名参数调用其Create()方法时,它会将其传递到字典: class DynamicDictionaryFactory : DynamicObject { public override b
DynamicDictionary
示例,它允许您使用字典,就像它是一个具有属性的类一样
以下是课程(为简洁起见稍作修改):
问题
DynamicObject
提供了,这是针对这种情况的,但在C#中不可用
我看到了一些解决方法:
Create()
方法时,它会将其传递到字典:
class DynamicDictionaryFactory : DynamicObject
{
public override bool TryInvokeMember(
InvokeMemberBinder binder, object[] args, out object result)
{
if (binder.Name == "Create")
{
// use binder.CallInfo.ArgumentNames and args
// to create the dynamic dictionary
result = …;
return true;
}
return base.TryInvokeMember(binder, args, out result);
}
}
…
dynamic factory = new DynamicDictionaryFactory();
dynamic dict = factory.Create(Id: 42);
// has to implement IEnumerable, so that collection initializer works
class DynamicDictionary
: DynamicObject, IEnumerable<KeyValuePair<string, object>>
{
public void Add(string name, object value)
{
m_dictionary.Add(name, value);
}
// IEnumerable implmentation and actual DynamicDictionary code here
}
…
dynamic dict = new DynamicDictionary { { "Id", 42 } };
使用开源的ImpromptuInterface(通过nuget),它有一个。这使您可以执行一些接近初始化语法的操作。特别是在包含
ImpromptuInterface.Dynamic之后
var result = Enumerable.Range(1, 5).Select(i => Build<DynamicDictionary>.NewObject
(
Id: i,
Foo: "Foo",
Bar: 2
));
var result=Enumerable.Range(1,5)。选择(i=>Build.NewObject
(
Id:我,
福:“福”,
酒吧:2间
));
该语法页面上还列出了其他选项,如果您删除
,它将使用本质上相同的即兴词典。您也可以查看构建语法的 事实证明,我能够通过使用Linq的内置ToDictionary()
方法解决我的问题
例如:
public Test()
{
var data = Enumerable.Range(1, 5).Select(i => new
{
Id = i,
Foo = "Foo",
Bar = 2
});
var result = data
.Select(d => d.GetType().GetProperties()
.Select(p => new { Name = p.Name, Value = p.GetValue(pd, null) })
.ToDictionary(
pair => pair.Name,
pair => pair.Value == null ? string.Empty : pair.Value.ToString()));
}
当我看到这样的嵌入式语言模式时,我倾向于使用扩展方法,因此我可以编写以下代码来实现我的目标:
public Test()
{
var data = Enumerable.Range(1, 5).Select(i => new
{
Id = i,
Foo = "Foo",
Bar = 2
}.AsDynamicDictionary());
}
然后,我将使用代码定义扩展方法,以将任何对象
(包括匿名键入的对象)转换为DynamicDictionary
:
public static class DynamicDictionaryExtensions
{
public static DynamicDictionary AsDynamicDictionary(this object data)
{
if (data == null) throw new ArgumentNullException("data");
return new DynamicDictionary(
data.GetType().GetProperties()
.Where(p => p. && p.CanRead)
.Select(p => new {Name: p.Name, Value: p.GetValue(data, null)})
.ToDictionary(p => p.Name, p => p.Value)
);
}
}
您必须在DynamicDictionary
中实现构造函数才能接收IDictionary
,但这是小菜一碟。对象初始值设定项不适用于dynamicobjects@Magnus,从技术上讲,它可以处理动态对象,但只能以非动态方式。因此,如果动态对象具有非动态Id
属性,则可以使用对象初始值设定项。但这无助于回答这个问题。没错,对于“正常”属性,它可以正常工作。我想你可以添加一个构造函数,它接受IEnumerable
并使用它来创建字典p、 CanRead
您似乎遗漏了一些内容。
public Test()
{
var data = Enumerable.Range(1, 5).Select(i => new
{
Id = i,
Foo = "Foo",
Bar = 2
});
var result = data
.Select(d => d.GetType().GetProperties()
.Select(p => new { Name = p.Name, Value = p.GetValue(pd, null) })
.ToDictionary(
pair => pair.Name,
pair => pair.Value == null ? string.Empty : pair.Value.ToString()));
}
public Test()
{
var data = Enumerable.Range(1, 5).Select(i => new
{
Id = i,
Foo = "Foo",
Bar = 2
}.AsDynamicDictionary());
}
public static class DynamicDictionaryExtensions
{
public static DynamicDictionary AsDynamicDictionary(this object data)
{
if (data == null) throw new ArgumentNullException("data");
return new DynamicDictionary(
data.GetType().GetProperties()
.Where(p => p. && p.CanRead)
.Select(p => new {Name: p.Name, Value: p.GetValue(data, null)})
.ToDictionary(p => p.Name, p => p.Value)
);
}
}