Что лучший способ состоит в том, чтобы объединить два объекта во время времени выполнения с помощью C#?

Можно сделать это при помощи символа ESC, '\' перед фигурными скобками.

# to print '{I am inside braces}'
print('\{I am inside braces\}')

Примечание, что символы ESC также используются, чтобы сделать некоторый специальный тип задач, как - '\n' для новой строки, '\t' для tabspace. Так, используйте их соответственно.

6
задан Dale Ragan 1 September 2009 в 15:17
поделиться

7 ответов

Если вы не возражаете, чтобы они были сгруппированы, а не объединены :

public class FooEx<T>
{
    public Foo Foo { get; set; }
    public T Ex { get; set; }
}
8
ответ дан 8 December 2019 в 17:24
поделиться

К сожалению, это нелегко. Лучшее, что вы можете сделать, - это создать анонимный тип как часть запроса LINQ, но у него будет только локальная область видимости, и поэтому он будет вам полезен только в том методе, в котором вы его создаете.

Когда выйдет .NET 4, появится новая динамическая библиотека времени выполнения, которая может вам помочь.

2
ответ дан 8 December 2019 в 17:24
поделиться

Помимо вопроса «Почему?», Единственный способ, которым я могу придумать, взять два объекта, один известный и один неизвестный, и объединить их в новый тип, - это использовать Reflection.Emit для генерировать новый тип во время выполнения.

Примеры есть в MSDN. Вам нужно будет определить, хотите ли вы объединить поля с одинаковыми именами или чтобы известный тип заменял неизвестный тип.

Насколько я могу судить, в LINQ нет способа сделать это.

Поскольку все, что вас интересует, - это свойства, поэтому использовать эту статью в качестве примера должно быть довольно просто. Оставьте il для создания методов, и все готово.

1
ответ дан 8 December 2019 в 17:24
поделиться

Как указывали другие, нет способа "объединить" их (например, если вы думаете о select * с несколькими таблицами в SQL) . Ваш ближайший аналог мог бы пойти по маршруту, предоставленному Zxpro, и «сгруппировать» их в общий класс.

Но что именно вы хотели бы достичь с помощью «слияния» их? Явное объявление свойств окажет наибольшее влияние на удобство написания кода и безопасность во время компиляции, но если вы не можете указать тип, для этого нет возможности. Если вы просто ищете общий контейнер «мешок свойств», то существующая структура данных, такая как Dictionary или Hashtable , должна справиться с этим. .

0
ответ дан 8 December 2019 в 17:24
поделиться

Если вы можете добавить метод к классу метаданных, вы можете сделать что-то вроде следующего

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; }
}

Я не уверен, что рекомендую именно этот подход. Я в основном оставил его здесь, чтобы отображать анонимные типы как возможный вариант, который может быть стоит изучить

0
ответ дан 8 December 2019 в 17:24
поделиться

Другой вариант:

Измените первый класс следующим образом

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;

}

Установите свойство Any в XmlElement и сериализуйте Это Вы увидите XML для другого класса, встроенного в документ, вместе со всеми пространствами имен

. Вы даже можете избежать этого, если класс был сгенерирован с помощью Xsd.exe, если вы используете следующий элемент в качестве элемента:

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

Я считаю, что вы также можете обойтись без массива XmlElements для более чем одного подкласса.

Десериализация должна заключаться в проверке XmlElements и последующем поиске соответствующего класса или, возможно, с использованием пространства имен для поиска класса .

Это намного проще, чем возиться с манипуляциями со строками.

0
ответ дан 8 December 2019 в 17:24
поделиться

НЕ ПРОВЕРЕНО, но с использованием API Reflection.Emit должно работать примерно следующее:

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));
3
ответ дан 8 December 2019 в 17:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: