-->

什么是用C#在运行时合并两个对象的最佳方式?(What is the best way to mer

2019-08-03 06:20发布

我有两个对象,我想将它们合并:

public class Foo
{
    public string Name { get; set; }
}

public class Bar
{
    public Guid Id { get; set; }
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }
    public string Property4 { get; set; }
}

创造:

public class FooBar
{
    public string Name { get; set; }
    public Guid Id { get; set; }
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }
    public string Property4 { get; set; }
}

我只知道美孚在运行时的结构。 酒吧可以是任何类型的在运行时。 我想有一个将被赋予一个类型,并将其与美孚合并该类型的方法。 例如,上面的方案中,该方法给出在运行时直板型和我与富结合它。

什么是做到这一点的最好方法是什么? 可以在使用LINQ表达式完成或做我必须动态地生成它还是有另一种方式? 我仍然在学习C#3.0中新的LINQ的命名空间,所以原谅无知,如果它不能使用LINQ表达式来完成。 这也是我第一次曾经有过用C#做一些动态的这个样子,所以我不太肯定的所有我提供给我的选项。

感谢您给予的任何选项。

编辑


这是严格添加的元信息来给我进行序列化的类型。 这种情况下保持了用户的对象无知的,需要加以补充,这是连载前的元信息。 我想出了两个选项问这个问题之前,我只是想看看是否有下去了,决定使用哪一个之前。

我想出了这两个选项是:

操纵其序列,通过添加元数据信息后,给我的类型的序列化的字符串。

包裹给我的类型,它是类似于@Zxpro提到,但我略有不同,这是罚款。 它只是让我的API的用户必须遵循约定,这不是一件坏事,因为大家就要约定优于配置:

public class Foo<T>
{
    public string Name { get; set; }
    public T Content { get; set; }
}

编辑


谢谢大家对他们的答案。 我决定在包装对象像上面我给的答案@Zxpro,因为大多数喜欢这种做法也。

如果任何人遇到了这个问题,随意张贴,如果你认为有可能是一个更好的办法。

Answer 1:

如果你不介意他们进行分组,而不是合并

public class FooEx<T>
{
    public Foo Foo { get; set; }
    public T Ex { get; set; }
}


Answer 2:

未经测试,但使用Reflection.Emit的API,这样的事情应该工作:

public Type MergeTypes(params Type[] types)
{
    AppDomain domain = AppDomain.CurrentDomain;
    AssemblyBuilder builder = 
        domain.DefineDynamicAssembly(new AssemblyName("CombinedAssembly"),
        AssemblyBuilderAccess.RunAndSave);
    ModuleBuilder moduleBuilder = builder.DefineDynamicModule("DynamicModule");
    TypeBuilder typeBuilder = moduleBuilder.DefineType("CombinedType");
    foreach (var type in types)
    {
        var props = GetProperties(type);
        foreach (var prop in props)
        {
            typeBuilder.DefineField(prop.Key, prop.Value, FieldAttributes.Public);
        }
    }

    return typeBuilder.CreateType();


}

private Dictionary<string, Type> GetProperties(Type type)
{
    return type.GetProperties().ToDictionary(p => p.Name, p => p.PropertyType);
}

用法:

Type combinedType = MergeTypes(typeof(Foo), typeof(Bar));


Answer 3:

不幸的是,这是不是你可以轻松做到。 你能做的最好的是创建一个匿名类型为LINQ查询的一部分,但只会有局部的范围,所以只会对你有好处的方法,其中,你把它。

当.NET 4中出来的时候,有一个新的动态运行时库,可以帮助你。



Answer 4:

除了这个问题:“为什么”,只有这样我能想到把两个对象,一个已知的和未知的一个,并把它们合并成一个新的类型是使用Reflection.Emit的生成一个新的类型在运行时。

有MSDN上的例子。 你必须确定你想合并是有相同的名字,或是有已知类型取代未知类型字段的天气。

据我所知,有没有办法在LINQ做到这一点。

因为所有你感兴趣的是属性应该是很容易使用这篇文章作为一个例子。 离开了金正日创建方法,你是好去。



Answer 5:

正如其他人所指出的那样,没有办法“合并”他们(如果你正在考虑的一个select *在SQL多个表,例如)。 你最亲密的模拟将采取在一个泛型类Zxpro提供了路线和“群”它们。

,究竟是什么,你会不会想与“合并”他们,虽然来完成? 显式声明的属性会对编写代码最大的便利效果和编译时的安全性,但如果你不能指定一个类型,然后有针对没有机会。 如果你只是在寻找一个通用的“属性包”的容器,那么现有的数据结构,如Dictionary<T,T>Hashtable应该可以搞定。



Answer 6:

如果你可以添加一个方法到元数据类,你可以做类似以下

public class Foo
{
    public string Name { get; set; }
    public void SerializeWithMetadata(Bar bar)
    {
       var obj = new {
                       Name = this.Name,
                       Guid = bar.Guid,
                       Property1 = Bar.Property1
                      }
       //Serialization code goes here
    }
}

public class Bar
{
    public Guid Id { get; set; }
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }
    public string Property4 { get; set; }
}

我不知道我会建议这个确切的方法,我主要是离开这里显示匿名类型作为一个可能的选项,可能是值得探讨



Answer 7:

另外一个选项:

修改像这样的一流

public class Foo
{
    public string Name { get; set; }

    [System.Xml.Serialization.XmlAnyElementAttribute()]
    public XmlElement Any {get;set;}
}

就拿第二类并将其序列化到像这样的XmlElement的:

XmlElement SerializeToElement(Type t, object obj)
{
    XmlSerializer ser = new XmlSerializer(t);
    StringWriter sw = new StringWriter();
    using (XmlWriter writer = XmlWriter.Create(sw, settings))
        ser.Serialize(writer, obj);

    string val  = sw.ToString();

    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xmlString);

    return (XmlElement)doc.DocumentElement;

}

设置任何房产到的XmlElement,并对其进行序列化,您将看到XML的文档中嵌入的其他类,完成所有的命名空间

你甚至可以逃脱这个,如果你使用以下作为一个元素使用XSD.EXE生成的类:

<xs:any namespace="##any" processContents="lax" />

我相信你也可以逃脱XmlElements的超过一个子类的数组。

Deserializaing应检查XmlElements,然后寻找一个匹配的类,或者使用命名空间来找到类的问题。

这比字符串操作搞乱整洁了很多。



文章来源: What is the best way to merge two objects during runtime using C#?