Выборочное копирование членов класса, некоторые строки, некоторые классы - PullRequest
0 голосов
/ 07 мая 2019

Я пытаюсь написать эффективный код C # для копирования выбранных членов класса из объекта A в объект B на основе списка имен членов.У рассматриваемого класса будет комбинация строковых членов и членов класса.Вот пример макетов классов.

public class Class0
{
    public string C0Prop1 {  get; set; } = "c0.prop1";
}
public class Class1
{
    public string C1Prop1 { get; set; } = "c1.prop1";
    public string C1Prop2 { get; set; } = "c1.prop2";
}
public class Class2
{
    public string C2Prop1 { get; set; } = "c2.prop1";
    public Class1 C2Prop2 { get; set; } = new Class1();
    public string C2Prop3 { get; set; } = "c2.prop3";
    public string C2Prop4 { get; set; } = "c2.prop4";
    public Class0 C2Prop5 { get; set; } = new Class0();
}

Затем у меня есть функция foo (), в которой есть список 'props', которые являются именами некоторых членов Class2.

Моя цель состоит в том, чтобы иметь некоторый жесткий код, позволяющий мне копировать только C2Prop2 и C2Prop4 из исходного объекта в целевой объект.В конце концов 'props' передается в foo (), поэтому он будет динамическим, и foo () может скопировать любой из элементов.

foo()
{
    BindingFlags _flags = BindingFlags.GetProperty | BindingFlags.IgnoreCase |
                            BindingFlags.Instance | BindingFlags.Static |
                            BindingFlags.Public | BindingFlags.NonPublic |
                            BindingFlags.FlattenHierarchy;
    Class2 source = new Class2();
    Class2 dest = new Class2();
    List<string>    props = new List<string>() {  nameof(Class2.C2Prop2), nameof(Class2.C2Prop4) };

    foreach (string prop in props)
    {
        var s = source.GetType().GetProperty(prop, _flags).GetValue(source, null);
        if (s != null)
        {
            if (String.Compare(prop, nameof(Class2.C2Prop2), true) == 0)
            {   // one option could be json
                dest.C2Prop2 = JsonConvert.DeserializeObject<Class2>(JsonConvert.SerializeObject(s));
            }
            else 
            if (String.Compare(prop, nameof(Class2.C2Prop5), true) == 0)
            {   // another option for copy
                dest.C2Prop5 = source.C2Prop5;
            }
            else
            { // this is a simple string member, just assign it.
                dest.GetType().GetProperty(prop, _flags).SetValue(dest, s.ToString());
            }
        }
    }
}

Для этого примера я перебираю список 'props'и используя PropertyInfo, чтобы определить характеристики исходного элемента, а затем решить, является ли он классом или строкой, и сделать копию соответствующим образом.Я уверен, что должен быть более оптимальный способ общего копирования отдельного члена объекта класса из источника в место назначения, но я не могу до конца понять это.

Любая помощь по этому вопросу будет принята с благодарностью!

1 Ответ

0 голосов
/ 07 мая 2019

Мне удалось использовать GetSetMethod () и GetGetMethod () PropertyInfo как для исходного, так и для целевого объектов для выполнения общей копии.Конечно, это предполагает, что члены должны иметь общедоступные методы получения и установки, но эта логика позволила мне минимизировать объем кода.

Не стесняйтесь рекомендовать улучшения.

public void copyAttrs(List<string> props, ref Class2 source, ref Class2 dest)
{
    BindingFlags _flags = BindingFlags.GetProperty | BindingFlags.IgnoreCase |
                            BindingFlags.Instance | BindingFlags.Static |
                            BindingFlags.Public | BindingFlags.NonPublic |
                            BindingFlags.FlattenHierarchy;
    foreach (string prop in props)
    {
        var propSource = source.GetType().GetProperty(prop, _flags);
        var proDest = dest.GetType().GetProperty(prop,_flags);
        if ((propDest != null) && (propSource != null))
        {
            MethodInfo destSetMethod = propDest.GetSetMethod();
            MethodInfo sourceGetMethod = propSource.GetGetMethod();
            if ((destSetMethod != null) && (sourceGetMethod != null))
                destSetMethod.Invoke(dest, new object[] { sourceGetMethod.Invoke(source, null) });
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...