Гость
Map
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / инфо по закрытым полям автореализованных свойств / 10 сообщений из 10, страница 1 из 1
24.09.2021, 01:10
    #40099647
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
доброго времени,

чето туплю но разыгрался академический интерес:

можем мы как либо с помощью отражения или еще каких либо плясок с бубнами выйти на имя поля автореализованного свойства?

то есть к примеру:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
public class foo {

public string Name1 {get; set;}
public string Name2 {get;}
private string Name3 {get;}


public static KeyValuePair<string, string> GetInfo(object t) {
    //какая то магия которая вернет список вида:
    // item[0]: { Name1, <Name1>k_BackingField }
    // item[1]: { Name2, <Name2>k_BackingField }
    // item[2]: { Name3, <Name3>k_BackingField }
}

}



сборка строки вида PropertyName + "k_BackingField" не устроит ибо боюсь что нет гарантии что когда нибудь "k_" не станет "l_"
...
Рейтинг: 0 / 0
24.09.2021, 06:12
    #40099657
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
felix_ff
можем мы как либо с помощью отражения или еще каких либо плясок с бубнами выйти на имя поля автореализованного свойства?

Нет.
К примеру, у меня есть самописное свойство с backing field:
Код: c#
1.
2.
bool [имя_поля];
public bool SomeProperty => [имя поля];


- сможете угадать, как на самом деле называется [имя поля]?
Рихтер, помнится, наезжал на auto-implemented properties в т.ч. по той причине, что они с очередным релизом фреймворка могут сломать бинарную сериализацию - она сериализует backing fields этих свойств, а очередной релиз может поменять схему именования полей.
Так что в данном случае - только полагаться на эмпирику по составлению наименования этих backing fields.
Еще, как вариант, можно задействовать Mono.Cecil, и распарсить IL тело аксессора свойства:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
namespace test2
{
  class Program
  {
    static void Main()
    {
      using (var fs = new FileStream(typeof(Foo).Assembly.Location, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
      {
        var assembly = AssemblyDefinition.ReadAssembly(fs);
        var toInspect = assembly.MainModule
          .GetTypes()
          .Single(t => "test2.Foo".Equals(t.FullName, StringComparison.Ordinal))
          .Methods
          .Single(m=> m.HasBody && m.IsGetter && "get_Bar".Equals(m.Name, StringComparison.Ordinal));
        foreach (var instruction in toInspect.Body.Instructions)
          Console.WriteLine($"{instruction.OpCode} \"{instruction.Operand}\"");
      }
  }

  class Foo
  {
    public Foo(string bar) => Bar = bar;
    public string Bar { get; }
  }
}


В консоли будет

Код: plaintext
1.
2.
ldarg.0 ""
ldfld "System.String test2.Foo::<Bar>k__BackingField"
ret ""
...
Рейтинг: 0 / 0
24.09.2021, 11:21
    #40099702
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
Сон Веры Павловны,

да соглсаен, проспался и понял что занимался ерундой.

у нас же никто не гарантирует что там за кулисами именно поле:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
public class foo {
  private _d1 double;
  private _d2 double;

  public double Value {
     get { return _d1 / _d2; }
     set { Calculator.Calculate(out _d1, out d2, value );}
  }
}



я кстати и озаботился этим вопросом собственно разбираясь с сериализацией, (правда xml) но суть проблемы таже
в случае если к примеру у нас есть закрытое приватное автосвойство только с аксессором get как в таком случае десериализовать объект? (с сериализацией все норм)

Код: sql
1.
2.
3.
4.
5.
public class foo {
    private int _myValue {get;}
    public foo(int value) {_myValue = value}
    
}
...
Рейтинг: 0 / 0
24.09.2021, 11:58
    #40099714
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
felix_ff
я кстати и озаботился этим вопросом собственно разбираясь с сериализацией, (правда xml) но суть проблемы таже
в случае если к примеру у нас есть закрытое приватное автосвойство только с аксессором get как в таком случае десериализовать объект? (с сериализацией все норм)

Тут только делать самописную сериализацию. Стандартная XML-сериализация вообще имеет жесткие ограничения, в частности:
1. Класс должен быть public, non-nested, и иметь public-конструктор без параметров;
2. Сериализуемые свойства должны быть public, должны иметь оба акссесора (и get, и set), и оба эти аксессора должны быть public.
И поэтому она часто неудобна.
Десериализация по полям с закрытыми сеттерами - ну, тут или рефлекшн (что медленно), или можно посмотреть, как это сделано в Dapper - он вполне умеет делать это. Вроде как там это реализовано через Reflection.Emit.
...
Рейтинг: 0 / 0
24.09.2021, 12:30
    #40099722
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
Сон Веры Павловны

Тут только делать самописную сериализацию. Стандартная XML-сериализация вообще имеет жесткие ограничения, в частности:
...
И поэтому она часто неудобна.


да согласен, но она позволяет использовать реализацию IXmlSerializable что по сути дает возможности той же бинарной сериализации.

Десериализация по полям с закрытыми сеттерами - ну, тут или рефлекшн (что медленно), или можно посмотреть, как это сделано в Dapper - он вполне умеет делать это. Вроде как там это реализовано через Reflection.Emit.

тут проблема именно в том что закрытого сеттера на свойстве нет. если смотреть MethodInfo по свойству видно что getMethod есть, а setMethod = null;

любой вызов из Reflection.InvokeMember / SetValue вызывает исключение ArgumentException: property set mthod not found. что и логично, поскольку установить значение можно только в конструкторе, или явно задав значение backing полю.

этот пример явно притянут за уши, и я понимаю что по факту свойство должно тогда бы было объявляться как
Код: sql
1.
  private int Value {get; private set; } 



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


Про Dapper, сейчас покопаюсь проверю может ли он десиреализовавать такие конструкции, если получится покопаюсь в кишках, спасибо
...
Рейтинг: 0 / 0
24.09.2021, 14:35
    #40099754
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
Да, посмотрел dapper там создается ILGenerator и начинается сборка динамического метода по метаданным класса. мудрено однако :)
...
Рейтинг: 0 / 0
24.09.2021, 16:55
    #40099847
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
felix_ff,

"да соглсаен , проспался и понял что занимался ерундой."

а, так значит был не проспавшись, да и сейчас, судя по всему в таком же состоянии
...
Рейтинг: 0 / 0
29.09.2021, 07:58
    #40100575
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
felix_ff
собственно разбираясь с сериализацией

Контракт и Соглашения - на этом всё держится.

Сон Веры Павловны
Стандартная XML-сериализация вообще имеет жесткие ограничения, в частности:
1. Класс должен быть public, non-nested, и иметь public-конструктор без параметров;
2. Сериализуемые свойства должны быть public, должны иметь оба акссесора (и get, и set), и оба эти аксессора должны быть public.

Вот это и есть описание соглашений по умолчанию.

Но можно задать и явный контракт. Например, с помощью атрибутов.


По аналогии следует делать и самописную сериализацию. Либо опираемся на некоторые соглашения: например, сериализуем только публичные свойства. Либо описываем некий контракт: навешиваем атрибуты на те члены, которые нужно сериализовать, или реализуем определённый интерфейс. Или задаём контракт ещё как-то: передаём в конструктор сериализатора список полей/свойств, например. Насочинять можно много.

В любом случае, повторюсь ещё раз, есть либо неявные соглашения (но они всё равно явно описаны в документации используемого сериализатора), либо явно заданный контракт.
А опираться на BackingField действительно не стоит. Оно и под соглашения не попадает и контрактом не является.


P. S. Почему практически всегда, когда говорят о XML-сериализации, имеют в виду XmlSerializer? Семейство DataContractSerializer'ов имеет свои достоинства. Serialization guidelines - авось кому пригодится.
...
Рейтинг: 0 / 0
01.10.2021, 19:22
    #40101438
felix_ff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
petalvik,

тут та же проблема, при сериализации автореализованного свойства только с методом акссесором get при использовании DataContractSerializer будет ругаться что у свойства нет метода set, это документированно.

но представим себе ситуацию что нужно реализовать сериализацию такого класса:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
public class foo {
   public string Name1 {get;set;}
   private string Name2 {get;}

   public foo(){
     Name2 = Guid.NewGuid().ToString();
   } 
}



при этом воссоздать оба свойства.
...
Рейтинг: 0 / 0
01.10.2021, 21:41
    #40101462
Roman Mejtes
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
инфо по закрытым полям автореализованных свойств
felix_ff
petalvik,

тут та же проблема, при сериализации автореализованного свойства только с методом акссесором get при использовании DataContractSerializer будет ругаться что у свойства нет метода set, это документированно.

но представим себе ситуацию что нужно реализовать сериализацию такого класса:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
public class foo {
   public string Name1 {get;set;}
   private string Name2 {get;}

   public foo(){
     Name2 = Guid.NewGuid().ToString();
   } 
}



при этом воссоздать оба свойства.

какая то ересь, приватное поле? ну допустим, если бы в нем была логика, я бы еще поверил, но лучше использовать просто метод и приватное поле. Это и по скорости лучше. Если поле приватное, не кто не может его менять кроме самого этого класса и точка.
Меня лично, это вполне устраивает, это основы ООП, так сказать заповедь.
Вот с конструкторами, это да, подстава, но классы моделей обычно не имеют конструктора вообще, дефолтный и им норм, другие классы обычно не стерилизуют, если только в каких то особых случаях. Вообще по факту, такие вещи лучше начинать с xsd схемы, потом генерировать модель налету или, что сейчас модно, молодёжно?
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / инфо по закрытым полям автореализованных свойств / 10 сообщений из 10, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]