Одинаковые имена переменных - 2 разных класса - Как скопировать значения из одного в другое - Отражение - C # - PullRequest
6 голосов
/ 20 мая 2011

Без использования AutoMapper ... (потому что кто-то, ответственный за этот проект, будет гадить, когда увидит зависимости)

У меня есть класс (класс A) с множеством свойств. У меня есть другой класс (класс B) с теми же свойствами (те же имена и тип). Класс B также может иметь другие не связанные переменные.

Существует ли какой-нибудь простой код отражения, который может копировать значения из класса A в класс B?

Чем проще, тем лучше.

Ответы [ 5 ]

22 голосов
/ 20 мая 2011
Type typeB = b.GetType();
foreach (PropertyInfo property in a.GetType().GetProperties())
{
    if (!property.CanRead || (property.GetIndexParameters().Length > 0))
        continue;

    PropertyInfo other = typeB.GetProperty(property.Name);
    if ((other != null) && (other.CanWrite))
        other.SetValue(b, property.GetValue(a, null), null);
}
4 голосов
/ 20 мая 2011

Это

static void Copy(object a, object b)
{
    foreach (PropertyInfo propA in a.GetType().GetProperties())
    {
        PropertyInfo propB = b.GetType().GetProperty(propA.Name);
        propB.SetValue(b, propA.GetValue(a, null), null);
    }
}
1 голос
/ 20 мая 2011

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

public static Action<TIn, TOut> GetMapper<TIn, TOut>()
{
    var aProperties = typeof(TIn).GetProperties();
    var bType = typeof (TOut);

    var result = from aProperty in aProperties
                 let bProperty = bType.GetProperty(aProperty.Name)
                 where bProperty != null &&
                       aProperty.CanRead &&
                       bProperty.CanWrite
                 select new { 
                              aGetter = aProperty.GetGetMethod(),
                              bSetter = bProperty.GetSetMethod()
                            };

    return (a, b) =>
               {
                   foreach (var properties in result)
                   {
                       var propertyValue = properties.aGetter.Invoke(a, null);
                       properties.bSetter.Invoke(b, new[] { propertyValue });
                   }
               };
}
0 голосов
/ 05 января 2018

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

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

var json = JsonConvert.SerializeObject(a);
var b = JsonConvert.DeserializeObject<T>(json);
0 голосов
/ 20 мая 2011

Попробуйте это: -

PropertyInfo[] aProps = typeof(A).GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);

PropertyInfo[] bProps = typeof(B).GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);

    foreach (PropertyInfo pi in aProps)
                {
                    PropertyInfo infoObj = bProps.Where(info => info.Name == pi.Name).First();
                    if (infoObj != null)
                    {
                        infoObj.SetValue(second, pi.GetValue(first, null), null);
                    }
                }
...