Tworzenie IEnumerable z prop klasy

0

W jaki sposób stworzyć sobie obiekt IEnumerable popertsów z instancji klasy. Obecnie mam w klasie 10 propertsów i przy tworzeniu instancji danej klasy ( służy jako kontener danych wypełniam je osobno..... np:

entity.add {new Entity({

FaceFront = cośtam,
FaceLeft = cośtam.....

itd.

})}
 

Jest jakiś elegancki sposób stworzyć jakiś obiekt IEnumerable, żeby w pętli wypełnić 11 właściwości klasy np. stringiem "null" i dodać do instancji klasy ?

No chyba, żeby to zrobić przez konstruktor ale w chwili zrezygnowania z klasy jako kontenera i zastąpić go strukturą ?

0

Możesz też przerzucić wszystkie pola klasy do słownika, wtedy można przelecieć pętlą i uzupełnić każdy z elementów wartością domyślną, ale mimo wszystko chyba bym wolał defaultowy konstruktor, który wewnętrznie w klasie załatwi sprawę, bo obsługa takiej instancji gdzieś poza obiektem może Ci się w przyszłości odbić czkawką.

0

Nie rozumiem co ma do tego IEnumerable.

Możesz oczywiście zrobić konstruktor który przyjmie 11 parametrów, ale to chyba gorsze rozwiązanie niż obecne, bo nie będzie widać który parametr oznacza „front”, który „back”...

W czym ci przeszkadza obecne rozwiązanie?

0

zapewne da się te własności pogrupować w większe, związane ze sobą obiekty, potem przekazywać te obiekty
można użyć wzorca fabryki

Azarien napisał(a):

Możesz oczywiście zrobić konstruktor który przyjmie 11 parametrów, ale to chyba gorsze rozwiązanie niż obecne, bo nie będzie widać który parametr oznacza „front”, który „back”...

można zrobić konstruktor z domyślnymi wartościami typu:

public Konstruktor(int pierwszy = 0, string drugi = null, string trzeci = null, string czwarty = null)
{
//...
}

potem można przekazywać tylko te wartości które chcemy zmienić:

var obiekt = new Konstruktor(pierwszy: 5, czwarty: "tekst");

reszta przyjmie wartości domyślne

0
wedlock napisał(a):

W jaki sposób stworzyć sobie obiekt IEnumerable popertsów z instancji klasy.

co do tej części pytania - możesz to zrobić używając refleksji:

typ.GetProperties().AsEnumerable();

w GetProperties możesz dać dodatkowe flagi, jak na przykład System.Reflection.BindingFlags.Public aby uzyskać tylko własności publiczne

przykład uzupełniający wszystkie publiczne własności typu "string", instancji podanej klasy wartością "Cos":

        public class MyClass
        {
            public string Pierwszy { get; set; }

            public string Drugi { get; set; }

            public string Trzeci { get; set; }
        }

        static void Main(string[] args)
        {
            var nowaKlasa = new MyClass();

            var properties =
                nowaKlasa.GetType().GetProperties(
                    System.Reflection.BindingFlags.Instance |
                    System.Reflection.BindingFlags.Public |
                    System.Reflection.BindingFlags.SetProperty).AsEnumerable();

            foreach (var prop in properties)
            {
                if (prop.PropertyType == typeof(string))
                {
                    prop.SetValue(nowaKlasa, "cos", null);
                }
            }

            Console.WriteLine(nowaKlasa.Pierwszy); // "cos"
            Console.WriteLine(nowaKlasa.Drugi); // "cos"
        }
0
Azarien napisał(a):

Nie rozumiem co ma do tego IEnumerable.

Możesz oczywiście zrobić konstruktor który przyjmie 11 parametrów, ale to chyba gorsze rozwiązanie niż obecne, bo nie będzie widać który parametr oznacza „front”, który „back”...

W czym ci przeszkadza obecne rozwiązanie?

W klasie trzymam n.inn. BitmapImage ścian obiektu 3d. Wypełniam je wszystkie obiektem "ściana nie istnieje". W dalszej części kodu jeśli program znajdzie obrazek uzupełnia wpis. Pozostałe nie znalezione są ustawione "ściana nie istnieje". W obecnej formie "ściana nie istnieje" jest jedna ale może będzie ich więcej i w różnych kombinacjach np: dla jednej encji będzie "ściana nie istnieje1", "ściana nie istnieje99". I zmiana w kodzie stringu URI dla dażdego prop klasy wydaje mi się mało czytelne i eleganckie. A jak wrzucę w foreach to nawet nie będzie mnie interesowało ile będę miał ścian ( sześcian ma 6 a model kowadła..... naście ). Wydaje mi się to bardziej czytelne. Oczywiście dla utrzymania porządku klasa dziedziczy po moim interfejsie

0

pokaż kod bo jakoś sobie nie wyobrażam
na pewno da się to zrobić bardziej elegancko

użycie refleksji nie jest najlepszym pomysłem jeśli chodzi Ci o wydajność - ale podejrzewam że tę funkcję wypełniającą uruchamiałbyś tylko raz więc jest to bez znaczenia

0

Metoda GetProperties zwraca tablicę, a tablica jest IEnumerable sama z siebie. Ogólnie samo wybranie właściwości typu string można uprościć:

var properties = nowaKlasa.GetType()
    .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty)
    .Where(p => p.PropertyType == typeof(string));
0
yrteyerty napisał(a):

pokaż kod bo jakoś sobie nie wyobrażam

Siadłem dopiero do komputera... Kod odpowiadający za wypełnienie danych. Zrezygnowałem z wypełnienia najpierw listy obrazkami wskazującymi na"obrazek nie istnieje". W XAML-u dodałem (w widoku) IValueCOnverter który po otrzymaniu null zwraca BitmapImege - "obrazek nie istnieje". Dzięki temu zrezygnowałem z 1 pętli.

  var result = new List<Entity>();
           
            foreach (SerializedEntity block in knownBlocks)
            {
                result.Add(new Entity
                {
                    FaceBack = SearchAndSetImage(block.FaceBack, StreamFiles),
                    FaceBottom = SearchAndSetImage(block.FaceBottom, StreamFiles),
                    FaceFront = SearchAndSetImage(block.FaceFront, StreamFiles),
                    FaceLeft = SearchAndSetImage(block.FaceLeft, StreamFiles),
                    FaceRight = SearchAndSetImage(block.FaceRight, StreamFiles),
                    FaceTop = SearchAndSetImage(block.FaceTop, StreamFiles),
                    AnimationKeyFrames = SearchAndSetString(block.AnimationKeyFrames, StreamFiles),
                    ModelType = block.ModelType,
                    BlockName = block.BlockName.ToUpper(),
                });
            }

            for (int i = 0; i < result.Count; i++)
            {
                result[i].Resolution = GetBlockResolution(result[i]);
            } 

i ten kawałek kodu chciałem sobie zamienić na pętlę bo średnio mi się podoba. Metoda SearchAndSetImage zwraca ImageBitmap ImageSource. Co jakiś czas do interfejsu Entity dodaje nowe dane w miarę nowych potrzeb. Dziękuję za pokazanie magii z refleksjami ale z powodów wydajnościowych przejdę na struct i pozostawię ten kawałek kodu w takim stanie.

Dlaczego chcę użyć struct... no bo http://www.pzielinski.com/?p=1809.

1
wedlock napisał(a):

Dziękuję za pokazanie magii z refleksjami ale z powodów wydajnościowych przejdę na struct i pozostawię ten kawałek kodu w takim stanie.

Dlaczego chcę użyć struct... no bo http://www.pzielinski.com/?p=1809.

Obiekt, który trzyma referencje do kilkunastu stringów NIE jest dobrym kandydatem na strukturę.
I to nie jest też tak, że zmiana class na struct magicznie zwiększa prędkość aplikacji. Gdyby tak było, to nikt nie pisałby klas. Profilowałeś kod w wersji z class i struct, że wiesz, że ta zmiana coś Ci daje, czy po prostu uprawiasz teoretyczne mikrooptymalizacje bez związku z Twoim projektem?

Struktury tworzy się, gdy:

  1. stanowią logiczną całość złożoną z kilku prostych wartości (punkt, prostokąt, kolor RGB, data i czas);
  2. ich obiekty zajmują w pamięci <= 16 bajtów;
  3. są niezmienne po utworzeniu;
  4. nie podlegają częstemu pakowaniu/rozpakowywaniu ("konwersji" na object).
0

@Azarien, odpowiedzią na każde pytanie jest właściwie jedno zdanie: "bo struktury, to typy wartościowe".
Ale uszczegóławiając:
2 - W przypadku przekazywania do metody, cały obiekt typu wartościowego jest kopiowany. Kopiowanie trwa tym dłużej, im większy jest obiekt, więc jeśli chodzi nam o wydajność, to tworzenie dużych struktur nic nam nie da, lepiej użyć typu referencyjnego.
3 - Zmiana wartości jednej instancji struktury nie ma żadnego wypływu na jej kopie, a te są tworzone niejawnie, przy każdym ich przekazaniu do metody. To sprawia, że mutowalne struktury są tak naprawdę mało użytecznie, za to mogą powodować trudności w zrozumieniu tego, co się dzieje w kodzie. Lepiej utworzyć nową instancję o zmienionej wartości.

1 użytkowników online, w tym zalogowanych: 0, gości: 1