játékfejlesztés.hu
FórumGarázsprojectekCikkekSegédletekJf.hu versenyekKapcsolatokEgyebek
Legaktívabb fórumozók:
Asylum:    5441
FZoli:    4892
Kuz:    4455
gaborlabor:    4449
kicsy:    4304
TPG:    3402
monostoria:    3284
DMG:    3172
HomeGnome:    2919
Matzi:    2519

Pretender:    2498
szeki:    2440
Seeting:    2306
Geri:    2186
Orphy:    1893
Joga:    1791
Bacce:    1783
MaNiAc:    1735
ddbwo:    1625
syam:    1491
Korábbi postok
> 1 < [2] [3] [4] [5] [6] [7] [8] [9] [10] [15] [20] [25] [30] [35] [40] [45] [46]
Matzi - Szerkesztő | 2519 hsz       Online status #211386   2017.05.23 12:52 GMT+1 óra  
Szerintem nem feltétlenul a megoldásra gondolt, hanem arra hogy hogyan oldja meg kódból. Az már némileg trukkosebb, mert kell valamiféle reprezentáció az állapottérre, és azon kell optimalizálni egy legrovidebb utat.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
FZoli - Szerkesztő | 4892 hsz       Online status #211385   2017.05.23 12:27 GMT+1 óra  
áhh elkéstem, írni akartam, hogy nem olyan nehéz, akár simán a lehetőségek próbálgatásával is fejben percek alatt megoldható a feladat.
   
Lord_Crusare - Törzstag | 1287 hsz       Online status #211384   2017.05.23 12:20 GMT+1 óra  
Először át megy az 1 és 2 perces ürge (ez eddig 2 perc). Az 1 perces visszajön, visszahozza a lámpát (ez 3 perc). Ezután átmegy az 5 és 10 perces ürge (13 perc), a 2 perces vissza hozza a lámpát (15 perc). Végül az 1 és 2 perces is átmegy, és ez így 17 perc.

   
djlord - Tag | 1 hsz       Online status #211383   2017.05.23 10:54 GMT+1 óra  
Valaki eltudná küldeni nekem ennek a feladatnak a megoldását mert nem tudom megcsinálni és szükségem lenne rá hogy megértsem a működési elvét az ilyen programoknak előre is nagyon köszönöm ha valaki szán rám időt .


Négy ember át akar jutni egy híd egyik oldaláról a másikra. A hídon egyszerre
legfeljebb két ember mehet át. Az első embernek egymagában 1 perc, a
másodiknak 2 perc, a harmadiknak 5 perc, a negyedik pedig 10 perc szükséges
a hídon való átkeléshez. Ha ketten mennek egyszerre, akkor mindketten a
lassabban haladó tempójában ballagnak. Az átkeléshez adott és szükséges
tovább´a egy elemlámpa, amelyet magunkkal visznek az átkelők. (L´ampa
nélkül nem lehet átmenni.) Hogyan jutnak át mind a négyen a túlsó oldalra
17 percen belül?

   
Instalok - Tag | 532 hsz       Online status #210850   2017.01.26 09:09 GMT+1 óra  
Áh, annyi kizárt, hogy lesz, ráadásul a linkelt megoldás tök jól működik, még a selection-t is kezeli magától. Köszi!

   
Parallax - Tag | 574 hsz       Online status #210849   2017.01.26 08:58 GMT+1 óra  
Mindenképpen az utóbbi, vagyis lekérdezni a teljes listát, majd azon LINQ-zni és a memóriában manipulálni, ha valami változik, csak azt menteni. Amíg nem milliós nagyságrendű adatokkal dolgozol ez járható út.

   
Instalok - Tag | 532 hsz       Online status #210847   2017.01.25 14:05 GMT+1 óra  
Közben sikerült végre (talán) összeraknom, haladtam is kicsit tovább. Most viszont felmerült egy olyan kérdés, amire nem egyértelmű a válasz.

Adott egy DataGrid, ami elemeket jelenít meg. Van felette egy TextBox, amivel filterezni lehet a megjelenített dolgokat (bizonyos propertyje alapján). A helyzet ugye az, hogy a ViewModel nem közvetlen Entityvel babrál, hanem egy Entityt "wrappelő" objektummal. Ezeket az objektumokat egy megfelelő osztályon keresztül tudom lekérdezni (és létrehozni), azonban minden egyes lekérdezéskor új objektumok jönnek létre.

Úgy gondoltam, hogy a filterezés az ennek az osztálynak a feladata, azaz meghívom egy függvényét, ami visszaad egy IEnumerable<T>-t annak megfelelően, hogy milyen elemeket talált a feltétel alapján.

Ezt azonban megtehetné a ViewModel is: van egy listája az összes elemről (amihez új elem hozzáadásakor Addolni is tud), amit a létrejöttekor kért le a fent említett osztálytól. Ha nincs filter, akkor ezt a listát (ObservableCollection) adja vissza, ha van filter, akkor pedig Linq Extension függvényekkel magának filterezi a listát, és azt adja vissza.

Az utóbbi hatékonyabbnak tűnik (nem jönnek létre új objektumok), viszont logikailag nem feltétlen a ViewModelhez tartozik.

szerk.:
Bár, az is lehet, hogy ez teljes egészében a View feladata marad, meg lehet így is csinálni:
http://stackoverflow.com/questions/13815607/find-a-record-in-wpf-datagrid-by-typing

Ezt a hozzászólást Instalok módosította (2017.01.25 14:56 GMT+1 óra, 204 nap)

   
Parallax - Tag | 574 hsz       Online status #210844   2017.01.25 07:43 GMT+1 óra  
Láttam én is olyan projektet, ahol nem volt model se, hanem a view-be voltak belehekkelve az entitás objektumok közvetlen kezelése. Be is bukott a projekt, mert egyre kuszább, átláthatatlanabb lett az egész, mert azt hitték így gyorsabban haladnak. Tehát hosszútávon kell egy jól felépített architektúra és a TDD-re se árt rászokni, sokat segít a még jobb felépítésben és nem utolsó sorban nem kell soha félni, hogy valami elromlik és ez időben megtérül.

   
Instalok - Tag | 532 hsz       Online status #210840   2017.01.24 12:29 GMT+1 óra  
Hehe, igen, láttam a Resharpert sokan használják, egyelőre megvagyok nélküle. Amúgy pont megtaláltam a data validationt is, legalábbis az IDataErrorInfo részt, de látom van pár lehetőség (legalábbis .NET 4.5-től felfelé).

Olvasgattam meg néztem videókat még kicsit a témában, és megint elbizonytalanodtam. A legtöbb helyen a modelt egyként definiálják az entityvel. De ahogy írtad is, az nem úgy logikus (és biztonságos), ha az a két dolog elkülönített? Arról nem is beszélve, hogy a legtöbb leírásban a tényleges Data Access hardcode-olt, sehol nem használtak igazán Dependency Injectiont. Tehát nem is volt ennyi absztrakciós szint.

Tehát adott egy XEntity osztály, ami a tárolt (pl. adatbázisban) adatot reprezentálja:
Kód:
class XEntity
{
    // database mappingek a generáláshoz...
    // public propertyk...
}

Van egy IRepository, ami vissza tud adni XEntity collectiont, meg mondjuk el tud tárolni egy újat. Ez csak azért létezik interfészként, hogy ne a model layer feladata legyen eldönteni, hogy milyen adattárolót akar használni (így pl. a Unity/Functional Test használhat mock adatokat is)
Kód:
interface IRepository
{
    IEnumerable<XEntity> XEntities { get; }
    void AddX(XEntity);
}

Ezt a megfelelő "data provider" (azaz pl. egy MS SQL-t használó library) implementálja.

Ezután adott egy X osztály is, ami a külvilággal való kommunikációhoz kell. Tulajdonképpen wrappeli az XEntity-t, kiegészítheti különböző propertykkel is (pl. az entity egy PersonEntity, aminek van FirstName és LastName adatmezője, akkor a Person tartalmazhat egy FullName propertyt is, ami viszont nyilvánvalóan nincs ténylegesen tárolva - azaz nem része az entitynek):
Kód:
class X
{
    // public propertyk...
}

(1) Első körben úgy oldottam meg, hogy ez az osztály implementálja az INotifyPropertyChanged interfészt, így lehet erre bind-olni (amivel azonban már inkább a ViewModel rétegbe húz). Elgondolkoztam azon is, hogy ettől el kellene vonatkoztatom, és minden egyes megjelenítendő egységhez külön ViewModel osztályt létrehozni, ahol vannak olyan propertyk, amik küldik a notificationt. Persze ez sok extra (és fölösleges) kódolás lenne.

Nyilván ha van egy X akkor van sok X, szóval van egy Xs (vagy XList, XGroup, akármi) osztály is. Itt van a következő probléma:

(2) Ezt az osztályt használom arra, hogy az XRepository-n keresztül adatokat lekérjen és módosítson (de X objektumok segítségével). Első körben ez is implementálja az INotifyPropertyChanged interfészt, de látszik, hogy ez logikailag nem stimmel. Ennek az osztálynak csak annyi lenne a dolga, hogy több X-et vissza tudjon adni különböző feltételek mellett (összes, top 10, bizonyos property alapján, stb.)

Ha itt minden tiszta lenne, akkor az adott alkalmazás feladata annyi lenne, hogy:
- Létrehozza a megfelelő IRepository objektumot (az alkalmazás döntsön, hogy milyen adattárolót használ)
- A megfelelő View megkapja a megfelelő ViewModel(eke)t DataContextként

   
Parallax - Tag | 574 hsz       Online status #210838   2017.01.24 07:41 GMT+1 óra  
A CanExecute csak akkor engedi a gombot, amikor már minden valid. Közben a controlokra szépen rá lehet kötni error providert, ami irkálás közben jelzi a hibákat, de addig nem tudsz menteni, amíg a CanExecute nem engedi: DataValidation

Még, ami hasznos (C++ hoz is cool) a ReSharper. Ez akár DLL-eket is behúz a projektbe, ha valami nem található, de a név alapján rájön honnan való. Ezzel elég precízen is be lehet tartani a kódolási szabályokat, sok mindent kijavít, ismeri a legújabb nyelvi szabályokat, xaml kódot, mindent. (Sajnos fizetős, de le lehet szedni krackelten.) Valaki úgy megy interjúra, hogy előre megkérdezi van e ReSharper licensz.

   
Instalok - Tag | 532 hsz       Online status #210837   2017.01.23 18:15 GMT+1 óra  
Közben csináltam commandokat is, működik a CanExecute is, csak annyi a gondom így az egésszel, hogy a User nem kap visszajelzést, hogy miért nem tud mondjuk egy új terméket hozzáadni az adatbázishoz.

Azon gondolkoztam, hogy lesz egy error text is, amit hozzábindolok egy propertyhez. Azt a propertyt pedig a textbox által setelt propertyben fogom módosítani, attól függően, hogy helyes-e az input.

Meg az is lehet, hogy az egész CanExecute részt kihagyom, és akkor validálok, amikor a user rányom a gombra, mert minden egyes betűnyomásra áttúrni az adatbázist nem biztos, hogy túl szerencsés, ha megfelelő mennyiségű adat van.

   
Instalok - Tag | 532 hsz       Online status #210836   2017.01.23 15:49 GMT+1 óra  
Most már nekem is, csak meg kellett oldanom, hogy a resources-ok között ott legyen a data context. Érdekesen meg kell csavarni, mert nálam úgy néz ki, hogy adott ugye a Repository, aki közvetlenül az adatokkal machinál, a ViewModelnek pedig kell egy Repository objektum. Viszont ez nincs hardcode-olva, azaz kívülről kapja meg (az alkalmazás dönti el, hogy milyen Repositoryt használ, ha adatbázis, akkor milyet, stb.) konstruktor paraméterként.

Megoldottam csúnyán egy static propertyvel:
Kód:
// App
m_Repository = GetDBRepository();
Services.Initialize(m_Repository);

// ProductsView
public class ProductsView : Products
{
    public ProductsView()
        : base(Services.Repository)
    {
    }
}

Így már használható XAML szinten is:
Kód:
    ...
    DataContext="{DynamicResource ProductsView}" ResizeMode="NoResize">
<Window.Resources>
    <v:ProductsView x:Key="ProductsView"/>
</Window.Resources>

A commandokkal egyelőre nem foglalkoztam, de ez egy elég jó kis step-by-step dolognak tűnik. Ráadásul ezekben a témákban az MSDN doksi is elég jó, amennyire olvasgattam.

Annyi volt a bajom egyelőre a commandokkal, hogy kell neki egy másik Assembly (talán a WindowsBase nem tudom), viszont a Model model assemblyt (amiben a ModelView layer is van, hiszen az szorosabban kapcsolódik oda, mint máshova) nem szeretném egyéb dependenciákkal beszemetelni.

szerk.:
Viszont most jöttem rá, hogy mivel egyébként is csináltam egy ProductsView osztályt a View assemblyn belül, így használhatok commandokat is, amik csak simán meghívják az ősosztály függvényeit.

Ja és köszi a segítséget, valamiért elég nehéz volt most a felfogásom.

   
Parallax - Tag | 574 hsz       Online status #210835   2017.01.23 15:30 GMT+1 óra  
Nekem VS15-el érzékel mindent, még a nyelvi resource-öket is. A commandozást is próbáld az is jó dolog és be lehet állítani, hogy a parancs milyen esetben teljesülhet, ha nem, akkor automatán letiltja a gombot.

   
Instalok - Tag | 532 hsz       Online status #210834   2017.01.23 13:35 GMT+1 óra  
Hehe, akkor lehet jobban ránézek a WPF-re, csak eléggé szokni kell. A Winforms-t már nagyjából ismertem, de sebaj.

Rájöttem közben, hogy nem is feltétlen muszáj külön XY tulajdonságú listát visszaadni a ViewModel-ből, mert használható a DisplayMemberPath attribútum, viszont maga az adathalmaz kisebb, ha csak külön elemeket kérek le.

Azóta próbálgattam kicsit ezt a WPF binding dolgot, és elég jónak tűnik, kvázi csak propertyket kell írnom. Cserébe nekem valamiért az XAML-nél nem érzékeli a lehetséges propertyket, így nagyon figyelnem kell, hogy pontosan legyenek beírva.

   
Parallax - Tag | 574 hsz       Online status #210833   2017.01.23 13:14 GMT+1 óra  
Winforms alá sehogy, ott egy elem tulajdonságait tudod kötni controlokhoz és ennyi, a többit le kell kódolni. .NET-ben a winforms olyan, mint C++ nál a Win API, már nem nagyon használja senki.

   
Instalok - Tag | 532 hsz       Online status #210832   2017.01.23 13:02 GMT+1 óra  
Azt hiszem kezdem kapisgálni (csináltam egy mini WFP alkalmazást, ami megoldja a lenti feladatot) Szóval a ViewModel olyan objektumokat ad vissza, amikhez lehet bindolni. Tehát, ha akarok egy olyan listát, ami csak a Product neveket adja vissza, akkor a ViewModelnek van egy olyan propertyje, hogy ObservableCollection<string> ProductNames. A Notify meg gondolom azért kell, hogy ha a ViewModel átbuherálja a listát, akkor a View értesüljön róla.

Így, mivel az ObservableCollection-höz van bindolva, akkor kap értesítést arról, ha az elemek változnak, meg akkor is, ha maga a collection változik.

Ez valóban nem hülyeség, és sok glue-kódtól megkíméli az embert. Már csak azt kell megnézni, hogy Winforms alá hogyan lehet megcsinálni (bár ez a WPF sem tűnik rossz dolognak).

   
Parallax - Tag | 574 hsz       Online status #210831   2017.01.23 12:12 GMT+1 óra  
Ha WPF-et használsz, akkor kb ennyi lenne:
ViewModel
Kód:
Product selectedProduct;
public Product SelectedProduct
{
    get { return selectedProduct; }
    set
    {
        selectedProduct = value;
        NotifyPropertyChanged("SelectedProduct");
    }
}

ObservableCollection<Product> products;
public ObservableCollection<Product> Products
{
    get { return products; }
    set
    {
        products = value;
        NotifyPropertyChanged("Products");
    }
}


View
Kód:
<ListBox
    ItemsSource="{Binding Products, Mode=TwoWay}"
    SelectedItem="{Binding SelectedProduct, Mode=TwoWay}"/>

<TextBox Text=
    "{Binding SelectedProduct.Name, Mode=TwoWay,
    UpdateSourceTrigger=PropertyChanged}"/>

   
Instalok - Tag | 532 hsz       Online status #210830   2017.01.23 11:15 GMT+1 óra  
Na ja, ezt a binding dolgot még emésztenem kell. Ha saját magamnak kódolom le a controlok állítgatását, akkor tök jó, csak persze ennél lehet okosabban is. Esetleg tudnánk egy példát nézni? Úgy talán összeállna teljesen.

Tehát adott egy ProductEntity, ami a data layer része, ez kvázi egy adatbázis tábla 1:1 reprezentálása a kódban. Vannak mindenféle attribútumai, aminek segítségével lehet akár adatbázist is generálni.
Kód:
[Table(Name = "products")]
public sealed class ProductEntity
{
    [Column(Name = "id", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false, DbType = "INT NOT NULL IDENTITY")]
    public Int32 Id
    {
        get;
        set;
    }
   
    // Name, Quantity hasonlóan
}

Van egy Data Repository is (szintén a data layer része), amely az implementációtól függően a megfelelő helyről tud Entity-ket visszaadni (adatbázis, file, memória, stb.) Például az adatbázis-implementáció egyszerűen lekéri a táblát a DataContext segítségével:
Kód:
public class DBRepository : IRepository
{
    [Database(Name = "Stock")]
    private class Context : DataContext
    {
        public Table<ProductEntity> Products
        {
            get { return base.GetTable<ProductEntity>(); }
        }

        public Context(IDbConnection p_Connection)
            : base(p_Connection)
        {
        }
    }
   
    // ...
   
    IEnumerable<ProductEntity> IRepository.Products
    {
        get { return m_DataContext.Products; }
    }
}

A következő réteg a "ViewModel", ahol már olyan objektumok vannak, amelyeket a View direktben olvashat-írhat. Ott van például a Product osztály, ami egyetlen ProductEntity megfeleltetése (természetesen nincs Id propertyje, csak Name és Quantity).
Ha jól sejtem ez az osztály implementálhatná például az INotifyPropertyChanged interfészt. Ezt egyelőre meg is tettem, van egy BindableBase osztály, így kevesebbet kell kódolni:
Kód:
public sealed class Product : BindableBase
{
    private string m_Name;
    private int m_Quantity;
   
    public string Name
    {
        get { return m_Name; }
        set { base.SetProperty(ref m_Name, value, "Name"); }
    }
   
    public int Quantity
    {
        get { return m_Quantity; }
        set { base.SetProperty(ref m_Quantity, value, "Quantity"); }
    }
}

Továbbá van egy Products nevű osztály is, ami paraméterként vár egy IRepository-t (ezt használja a tényleges adatok olvasására-írására).
Kód:
public sealed class Products
{
    private IRepository m_Repository;

    public Products(IRepository p_Repository)
    {
        m_Repository = p_Repository;
    }

Ezen keresztül tud a View commandokat kiadni (egyelőre egyszerűen függvényhívásokkal), mint pl. egy új Product hozzáadása. Az Add() függvény egy Product objektumból egy ProductEntity-t készít, és megkéri a Repository-t, hogy tárolja el. Előtte természetesen leellenőrzi, hogy van-e már ilyen nevű product (az error kezelés egyelőre csak dummy, nem tudom még hogy lesz).
Kód:
public bool Add(Product p_Product, Action<string> p_Error)
{
    bool productNameAlreadyTaken = m_Repository.Products.Any(p => (p.Name == p_Product.Name));
    if (productNameAlreadyTaken)
    {
        p_Error(string.Format("Product name "{0}" is already taken", p_Product.Name));
        return false;
    }

    ProductEntity entity = new ProductEntity()
    {
        Name = p_Product.Name,
        Quantity = p_Product.Quantity
    };

    m_Repository.AddProduct(entity);

    return true;
}

Hasonlóan megy a teljes lista lekérdezése is:
Kód:
public List<Product> GetAll()
{
    var result = m_Repository.Products.Select(p => new Product()
    {
        Name = p.Name,
        Quantity = p.Quantity
    });

    return result.ToList();
}

Na most tegyük fel, hogy szeretnék egy Form-on egy ListView controlt és (egyelőre csak) két labelt. A ListView kilistázná az összes product nevét, a két label pedig kiírná a kijelölt listaelem nevét és mennyiségét.
Ez az egyszerűbb eset, mert ez az egy irányú binding, de ha ez összeáll, akkor szerintem oda-vissza is menni fog.

Ha kézzel akarnám lekódolni, az valahogy így nézne ki a Form-on belül:
Kód:
private Products m_Products; // a fentebbi Products osztály
private IList<Product> m_ProductList; // az összes Product
private Product m_Product; // a "kijelölt" Product

private Product CurrProduct
{
    get { return m_Product; }
    set
    {
        m_Product = value;

        // notify
        if (m_Product != null)
        {
            lblNameValue.Text = m_Product.Name;
            lblQuantityValue.Text = m_Product.Quantity.ToString();
        }
        else
        {
            lblNameValue.Text = "";
            lblQuantityValue.Text = "";
        }
    }
}

public MainForm()
{
    InitializeComponent();

    m_Products = new Products(Services.Repository);
    m_ProductList = m_Products.GetAll();
   
    CurrProduct = m_ProductList[0];
}

   
Parallax - Tag | 574 hsz       Online status #210829   2017.01.23 09:56 GMT+1 óra  
A databinding lényege, ahogy írtad oda-vissza (WPF-ben ez állítható is) automatikus adatkapcsolat. Listára is működik például a fa struktúrámban kitörlök valamit és ez rá van kötve egy TreeView-re, akkor az látszik is, ehhez nem kell külön programozni semmit. Ahogy kiválasztok egy node-ot, a SelectedItem is automatikusan kiválasztódik és mutatja az adatait is. Az adat lehet szöveg, kép stb, szépen realtime szerkesztődik minden a memóriában és, ha kiadod a mentés parancsot, akkor a megfelelő adatok a megfelelő táblába mentődnek a Model-en keresztül ellenőrzötten.

   
Instalok - Tag | 532 hsz       Online status #210828   2017.01.23 08:16 GMT+1 óra  
Igen, kell is még néhány módosítás. Azóta aludtam rá egyet, és valószínűleg az lesz, hogy ez a Products osztály nem Entityket fog visszaadni, hanem megjelenítendő modelleket, mert, ahogy írtad is, entityket nem használunk közvetlenül. A biztonságosabb kód mellett a további előnye a különböző konverziók lesznek, illetve az olyan propertyk megléte, amelyek nem részei az entitynek egyébként.

Ezt az automatikus bindolást használják egyébként mindenfelé a kódban. Lehet én is fogom, de nekem könnyebb követni, ha ott van az a glue kód, és látom, hogy mi-mit-mikor-miért csinál. Persze a másik sem bonyolult, csak nekem új.

Ha jól értettem a bindingnak a lényege az, hogy a ViewModel egy propertyje és a View egy UI eleme össze van kapcsolva, így, ha a ViewModel valamiért változik (például egy action hatására), akkor a View UI eleme is automatikusan változik, és nem kell ismételten lekérnem az adatokat. Illetve gondolom fordítva is igaz, ha a UI elemet szerkesztem (mert az pl. egy textbox), akkor a ViewModel kap egy értesítést, hogy az adott property változott.

Egy-egy elemre ezt így könnyű elképzelni, de mi van a listás megjelenítéssel? Van valami ObservableCollection is (ahogy lentebb említetted is).

Nekiállok ezt elolvasni, hátha le van írva szépen:
[url]https://msdn.microsoft.com/en-us/library/ms743643(v=vs.110).aspx[/url]

   
Parallax - Tag | 574 hsz       Online status #210827   2017.01.23 07:06 GMT+1 óra  
Entitást közvetlenül nem használunk semmire, mert bármilyen manipuláció történik azt úgy veszi, hogy az az adatbázissal történik és valahol elsül egy SaveChanges(), főleg, ha globális is, akkor ki tudja mi lesz.

A másik, hogy a model direkt a felületekre van felkészítve, a listában kiválasztott elem hozzá van kötve egy propertyhez, ha a lista változik a lista is automatikusan változik, ha adott elem bármilyen propertyje változik az a felületen automatikusan megjelenik és vissza. Igazából ez a .NET (WPF, ASP.NET MVC) előnye, ezek a kötési automatizmusok.

   
Instalok - Tag | 532 hsz       Online status #210825   2017.01.22 14:07 GMT+1 óra  
Valami hasonlót találtam ki azóta:

Vannak Entity osztályok, amik 1:1 megfeleltetése egy táblának. LINQ mapping segítségével attribútumokkal könnyen leírható, így akár adatbázis is generálható (nem kell kézzel).
Kód:
[Table(Name = "products")]
public sealed class ProductEntity
{
    [Column(Name = "id", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false,
            DbType = "INT NOT NULL IDENTITY")]
    public Int32 Id
    {
        get;
        set;
    }
   
    // ...


Az IDataProvider interfészt megvalósítja egy osztály, ami kvázi a táblák adatait szolgáltatja. Nem tud semmit, csak visszaadni egy IEnumerable<TEntity>-t, meg mondjuk van Add/Update/Remove függvénye is az adott típushoz. Egy ilyen megvalósítás például egy sql adatbázist használ (LINQ esetén nagyon kevés a kód, ott a DataContext meg a Table<T>, megoldanak mindent).
Kód:
public interface IDataProvider : IDisposable
{
    IEnumerable<ProductEntity> Products
    {
        get;
    }

    void AddProduct(ProductEntity p_Entity);
}


Továbbá van minden egyes logikai elemhez egy osztály, ami paraméterként vár egy IDataProvider-t, illetve az adott típushoz műveleteket definiál, ami vagy "beépített" típusokat, vagy Entity objektumokat ad vissza.
Kód:
public class Products
{
    public IEnumerable<ProductEntity> All()
    {
        return m_DataProvider.Products;
    }

    public bool Contains(int p_Id)
    {
        return m_DataProvider.Products.Any(p => (p.Id == p_Id));
    }
   
    // stb.
}


Ha nem akarnék további absztrakciós szintet, akkor a Products osztály használható lenne közvetlenül a View layer osztályaiban, azonban gyakran előfordulhat, hogy különféle konverziók, egyéb lekérdezések is kellenek, így tényleg érdemes lehet egy "ViewModel", vagy valami hasonló bevezetése.

Amin viszont elgondolkoztam, hogy lehet Entity szinten definiálni azt, hogy pl. egy Transaction nem egy ProductId-t ad vissza, hanem egy Product objektumot:
[url]https://msdn.microsoft.com/en-us/library/bb386950(v=vs.110).aspx[/url]

Ezt viszont megoldhatja a Products vagy Transactions osztály is, csak akkor kód szinten függőség alakul ki közöttük (meg kell kapniuk egymás referenciáját).

   
Parallax - Tag | 574 hsz       Online status #210824   2017.01.22 11:29 GMT+1 óra  
Instalok: Winforms, meg webforms az nem épp MVVM/MVC-re van kihegyezve, de persze plusz kódolással megolható a szemlélet.
Én valahogy így építeném fel az architektúrát:

Data: Adatbázist burkoló alrendszer pl.: Etity framework. 1-1 entitás osztály reprezentál 1-1 táblát. Szuboptimálisan hangzik, de minden lekérdezésnél létre kell hozni a kapcsolatot, utána pedig megszűntetni (dispose pattern). Ez desktop és főleg netes programnál így szokás különböző hibalehetőségek és egyebek miatt.

Model: Az entitások db független pehelysúlyú ábrázolása és különböző beépített lekérdezési lehetőségek, mint pl: authentikáció a User-nél. Ez arra jó, hogy a különböző felületek számára könnyen megjeleníthetőek és testreszabott műveleteket, konverziókat is tartalmazhatnak (serialization). Itt szokás külön egy és lista objektumokat definiálni: User, UserList, ahol a User lehet egy épp kiválaszott elem (NotificationObject), a lista (ObservableCollection) pedig a lekérdezett userek listája, amin műveleteket hajtunk végre és a végén mentés az adatbázisba.

ViewModel: Ez reprezentálja azt az adathalmazt (propertyk), és műveleteket (command pattern) amit a view/view-ek megjelenítenek. Itt nincs semmi platform specifikus dolog, és ide jöhet a validáció is (adott adat 1 és 100 közés eshet stb)

View: Ahogy írtad a view lenne egy buta felület, ami csak az adatok bevitelét, kiírását és bizonyos korlátok között manipulációkat végzi.

   
Instalok - Tag | 532 hsz       Online status #210823   2017.01.21 13:45 GMT+1 óra  
Az a feladat, hogy egy Windows Desktop (WinForms) alkalmazást kell készíteni, amivel egy adatbázist lehet vezérelni (módosítani, lekérdezni, semmi komoly).

A kérdésem arra irányulna, hogy WinForms esetén milyen megközelítést érdemes választani? Ami számomra fontos szempont:
- elkülönített business logic és presentation: később, ha kell, könnyedén lehessen írni egy webes megjelenítést is, ugyan azzal a backend kóddal.
- generikus data access layer: nem hardcode-olt SQL adatbázis-elérés, hanem ha kell, akkor lehessen mock adatokkal is dolgozni, vagy egyéb file-okból beolvasni (pl. xml).

Webfejlesztéskor megint más az egész, ott egy HTTP reqeust az új oldal betöltésekor megy, és kész, nincs permanens adat. Ott fekszik az MVC, ahol a requestet feldolgozza a controller, ha szükséges, nyit adatbáziskapcsolatot, lekéri/módosítja az adatokat, kiválasztja és létrehozza a view-t, majd végzett a munkával.

Desktop esetén pedig adott egy folyamatosan futó alkalmazás, ami maga a view. Valami olyasmit tudnék elképzelni, hogy adott egy Form, amely csak a megjelenítést végzi, tehát a "View". Adott egy logikai csoporthoz (pl. felhasználók kezeléséhez) tartozó "Controller", amin a View műveleteket hív, amely például visszaad egy objektumlistát lekérdezéskor. Maga a "Model" olyan osztályokból állna, amelyek az adatot reprezentálják, azaz kvázi egy adatbázis-tábla megfeleltetése.

Ez eddig szép és jó, de hiányzik a data-access, azaz, hogy mikor, kitől és hogyan kérem el az adatokat. Ez igazság szerint a controllerbe tartozik, hiszen a controlelr tudja, hogy milyen feltételekkel kell (pl.) lekérdezést végrehajtani. Még ha használok is valami általános dolgot (pl. LINQ esetén van DataContext), akkor is kérdéses, hogy kitől kapja meg ezt az objektumot, vagy magát a data source-ot (ami lehet sql connection, vagy file is). Overkill lenne minden egyes controller action esetén létrehozni egy új adatbáziskapcsolatot, majd a végén lezárni.

Milyen általános megközelítést lehetne használni desktop alkalmazás esetén?

   
Pixi - Tag | 205 hsz       Online status #208498   2015.10.19 13:52 GMT+1 óra  
Azt hogyan lehet megoldani, hogy az adott aplikáción kívülre is tudjunk utasítást küldeni az egérnek és a billentyűzetnek? Vagyis egér pozíció, gomblenyomás és billentyűzet gomblenyomás a cél, ezt kéne szimulálni programon kívül is. Az természetesen alap, hogy a háttérben futna egy program, ami magát ezt a funkciót biztosítja, ugyanis hálózaton keresztül kellene vezérelni mindezt. Vagyis egy adott üzenet biztosítaná kliens oldalon azt az eseményt, hogy éppen mit kell szimulálni. Ezt hogyan lehet megvalósítani, hogy ne csak az adott programon belül legyen érvényes?

szerk: Lényegében egy "Remote Desktop Controller" lenne a cél.

Ezt a hozzászólást Pixi módosította (2015.10.19 14:16 GMT+1 óra, 668 nap)

   
Parallax - Tag | 574 hsz       Online status #208099   2015.08.13 15:08 GMT+1 óra  
Idézet
Pixi :
Szerintetek hogyan legcélszerűbb egy telepítőt elkészíteni?

ClickOnce

   
Pixi - Tag | 205 hsz       Online status #208085   2015.08.11 13:10 GMT+1 óra  
Tunyu: Köszi, szerintem ez pont az amit én kerestem.

Matzi: Egyelőre úgy vagyok vele, hogy amit én magam is elkészíthetek, azt miért ne? Legalább ezzel is tanulhatok valami újat. Bár lehet, hogy tényleg kész megoldást fogok alkalmazni majd. Azt mondjuk nem tudom, hogy mi a gond azzal, ha mellékelve van pl. egy "software requirements" mappában a .net-es telepítő (offline, de akár online változata is), és ezen kívül lenne maga a .net-es program telepítő.exe + egy readme.txt. Vagy ezek szerint ez már a múlté, és egy laikus felhasználó ilyen környezetben nem tudja feltalálni magát? Mondjuk el tudom hinni sajnos. Azt amúgy nem is értem hogy lehet olyan telepítőt generálni, ami külön beavatkozás nélkül, vagy pedig automatikusan érzékeli és telepíti a gépre az aktuális .net verziót. Azt mondod, hogy van az a bizonyos adat file. Ha jól értelmezem, akkor ez még külön ott van a telepítő mellett ugye? És akkor akár egy darab nyers adat file-ba is bele tudom tenni az összes contentet + exe filet is, csak a telepítő programon belül pl. megmondom hogy x byte-tól y-ig ez egy "image1.png" a következő lépésben már egy exe file-t kel kiírni, stb.

   
Matzi - Szerkesztő | 2519 hsz       Online status #208084   2015.08.10 19:47 GMT+1 óra  
Idézet
Ha nem egy irányú lenne az SHA akkor csak azt használnám egyedül.
Az SHA nem titkosítás, hanem hash generálás. Annak a célja, hogy egy adatot átalakítson egy fix méretű másikká úgy, hogy kicsi legyen az ütközés esélye (két tetszőleges forrásból lehetőleg ne jöjjön ki ugyanaz a hash), de jelentősen csökkenjen méretben és ne lehessen visszafejteni. A titkosítás meg ugye nem akar elveszíteni adatot.

Pixi:
A legegyszerűbb, ha fogsz egy telepítő generáló programot, ami pont olyat csinál, mint bármelyik jelenleg is használt program telepítője. Biztos van ingyenes meg nyílt forráskódú is a neten.Az a baj, hogy ha külön akarod feltelepíttetni egy felhasználóval a .net-et, hogy ha még nincs a gépén, akkor jó eséllyel lövése sincs róla hogy mi az, és hogy előbb azt fel kellene tegye.
Mondjuk már a vistától felfelé a 3.0 az alap, de xp-n még külön fel kellett tenni. Szóval hacsak nem akarsz xpre is települni, akkor megírhatod .net-ben. Ilyenkor tipikusan van egy valamilyen adat file, akár lehet zip is, amit kicsomagolsz oda, ahová a user kéri, és esetleg telepítesz más programokat amik kellhetnek.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Tunyu - Tag | 447 hsz       Online status #208083   2015.08.10 15:32 GMT+1 óra  
Ha jól értem, akkor a válasz itt van.

   
Pixi - Tag | 205 hsz       Online status #208080   2015.08.10 10:34 GMT+1 óra  
Szerintetek hogyan legcélszerűbb egy telepítőt elkészíteni? Mennyire jó, ha maga a telepítő.exe egy komplet .NET-es alkalmazás? Valahogy úgy képzelem el, hogy van két fő file, az egyik a .net telepítő, amit a felhasználónak telepítenie kell 1x, ha az nincs a gépén, a másik maga a telepitő.exe, ami lehetne akár egy WinForm alkalmazás is (de végül is tökmind1 mi), és kisebb játékok esetén minden binárisan eltárolva ebben, tehát a kész projekt debug mappájában lévő anyagot betöltetném egy másik alkalmazásba, és ez íródna a tárolóra az előzőleg megadott útvonal szerint, ami már maga a telepítő.exe sajátos felépítésétől függ. A kérdés már csak az, hogyan oldják meg, hogy egy kész exe már magában tartalmazza nyersen az adatokat, tehát a különböző contenteket ne egy külső forrásból töltse be mindig, hanem már maga az exe része legyen? Mert ok, hogy program elindít, betölt minden adatot, de ezt ne kelljen külső forrásból töltögetnie. Úgy is kérdezhetném, hogy hogyan lehet a már lefordított aplikációt úgy debuggolni, hogy annak a része legyen a nyers adat? Gyanítom, hogy nem azt csinálják, hogy nyitnak minden egyes contetnek egy vagy több külön osztály.cs -t meg külön tömböt, és abba pakolgatják manuálisan byte-ok formájában a nyers adatokat. Vagy fölösleges ilyesmivel bajlódni, és bőven elég ma már egy kisebb játékot egy zip-be csomagolni, és úgy forgalmazni?

Ezt a hozzászólást Pixi módosította (2015.08.10 10:50 GMT+1 óra, 738 nap)

   
Tunyu - Tag | 447 hsz       Online status #208079   2015.08.09 16:49 GMT+1 óra  
Láttam én is hogy van újabb és fejlettebb az MD5-nél, de mivel már az SHA -1 is 40 karakteres kimeneti mérettel rendelkezik, az már nekem túl nagy, mert a 256 bites AES egy 32 karakteres kulcsot igényel.Az MD5 kulcs sehol nem lesz tárolva, azt majd a kliens oldal generálja a bejelentkezési adatból és küldi el a szervernek ahol ugyan ezzel a kulcsal vissza tudja fejteni és újra kódolni a játékos mentett adatait .Ha nem egy irányú lenne az SHA akkor csak azt használnám egyedül.

Ezt a hozzászólást Tunyu módosította (2015.08.09 17:56 GMT+1 óra, 738 nap)

   
Matzi - Szerkesztő | 2519 hsz       Online status #208078   2015.08.09 15:44 GMT+1 óra  
Ha ennyire fontos a biztonság, akkor használj mondjuk SHA-2-t vagy 3at, persze plusz só és bors.
Mondjuk kétszáz évre előre vetíteni gyakorlatilag lehetetlen. Lehet 50 év múlva beüzemelnek olyan kvantum processzorokat amik ezer bites titkosításokat reggeliznek. Általában annyi a cél, hogy az adatot több idő és pénz legyen feltörni, mint amennyit ér. Egy játék esetében ez nem feltétlenül nagy kitétel.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Tunyu - Tag | 447 hsz       Online status #208069   2015.08.07 21:29 GMT+1 óra  
Igen én is erre gondoltam hogy egy kis toldalékkal már egészen más hasht kapunk és az adatbázisban már nem valószínű hogy létezik olyan.
Csak egy játékot próbálok összehozni és annak a kliens és szerver oldali adatait próbálom a lehető legbiztonságosabb módon tárolni, hogy feltörés esetén se tudják visszafejteni az adatokat, vagy legalábbis 1-200 éven belül ne.

Na megoldottam, végül is jó ötlet volt az md5! A bejelentkezési adatból generálok egy sózott md5 hash-t és ezt használom fel a 256 bites kódoláshoz kulcsként.
A mentett adatok ezután így néznek ki:
Kód:
   ˙˙˙˙           Assembly-CSharp   RegData   ep      ,pMXNyuDfK7eriIPOuIvDkmIHp1E0ORWjs5/dDVNR/6E=   ZVsMJjj/MFbndyvC6POpPA==

Ezt a hozzászólást Tunyu módosította (2015.08.08 12:48 GMT+1 óra, 740 nap)

   
Matzi - Szerkesztő | 2519 hsz       Online status #208067   2015.08.07 20:23 GMT+1 óra  
Ezért szokták sózni borsozni, de felőlem használhatsz más hasht is. Csak példának mondtam. Ez csak akkor kell, ha félsz, hogy ellopják a szerverről a jelszó hasheket.
Játékot csinálsz, vagy valami biztonságkritikus rendszert?
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Tunyu - Tag | 447 hsz       Online status #208063   2015.08.07 12:23 GMT+1 óra  
Az md5 már kicsit elavult ahogy így utánanéztem.Le is teszteltem, egy md5 generátorral lekódóltam néhány szót, az md5 decrypter meg 10 mp múlva már dobta a string értékét. Persze nem értelmes szavaknál már nem biztos hogy ilyen egyszerű,de sok ember még mindig értelmes szavakat használ jelszónak.

   
Matzi - Szerkesztő | 2519 hsz       Online status #208061   2015.08.06 23:39 GMT+1 óra  
Ha valóban bármi lehet, és adott esetben ez nem ront az erősségén, akkor használhatod a jelszót, vagy akár a jelszó md5 hashét. Így egyből authentikál is a feloldáshoz. Ráadásul egy hasht nem gáz, ha mondjuk tárol egy szerver, jelszót nem nagyon illik nyersen tárolni amúgy sem.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Tunyu - Tag | 447 hsz       Online status #208056   2015.08.06 19:39 GMT+1 óra  
Én egy jól működő 256 bites AES titkosítást használok és a 32 karakter bármi lehet, az encrypt, decrypt nagyon szépen működik. Helyi adatokat email, jelszó és beállítási adatokat mentek így ki txt-be.Csak az a problémám vele hogy mivel a unity által létrehozott dll-t minden különösebb erőlködés nélkül vissza lehet olvasni, így simán hozzáférhető maga a kulcs is, és ezt akartam egy kicsit nehezíteni.

Valami olyasmi megoldás lenne jó amit a zip, rar-nál használnak,hogy a kulcsot nem tartalmazza a könyvtár... Erről jutott most eszembe,hogy maga a bejelentkezési adat lehetne a kulcs.

Ezt a hozzászólást Tunyu módosította (2015.08.06 19:46 GMT+1 óra, 741 nap)

   
Matzi - Szerkesztő | 2519 hsz       Online status #208055   2015.08.06 18:57 GMT+1 óra  
Non, azt senki nem mondta, hogy mindegy mi a kulcs.
A titkosítás ennél azért picivel bonyolultabb. Most nem olvastam utána pont az rc2-nek, de szinte kizártnak tartom, hogy működne bármilyen értékkel. A legtöbb titkosítás matematikai elven működik, pl prímszámokat használ, vagy más speciális tulajdonságú ritka kulcsokat. (A tévedés jogát fenntartom. ) Annyit tudsz csinálni, hogy generálsz egyet, és azt mondjuk eltárolod a program kódjában mint konstans. Vagy minden indításkor generálsz egyet, és amikor felveszed egy klienssel a kapcsolatot, akkor a kulcsot átküldöd titkosítatlanul, és utána használod. Persze ezt ki lehet használni az ún. man-in-the-middle módon. Esetleg használhatsz a kulcs átvitelére valami egyszerűbb titkosítást, pl sima xor, az valószínűleg elég, ha egy játékot írsz.
Ha esetleg bármi komolyabbat csinálnál, mondjuk üzleti alkalmazást, ahol kényes információk repkednek, akkor jobban jársz ha megveszel egy kész megoldást. Olcsóbb, mint megírni.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Tunyu - Tag | 447 hsz       Online status #208051   2015.08.06 04:45 GMT+1 óra  
Oké, köszi a választ! Én azt hittem hogy ez a kulcs valamiképpen az operációs rendszerhez és számítógéphez kötődik mert valami olyat olvastam hogy a kernel generálja.De akkor így mindegy ha én magam találom ki és pötyögöm be a 16 karaktert.

   
Matzi - Szerkesztő | 2519 hsz       Online status #208050   2015.08.06 00:51 GMT+1 óra  
Tunyu:
Ilyenről szó sincs. Generálsz egy kulcsot, az megőrzöd az életed árán is, és akkor azzal tudsz titkosítani, meg visszafejteni. Ha elveszíted, akkor már nem fog menni soha.

Tipikusan az történik, hogy generálsz egy kulcsot, azt elküldöd a másik félnek valahogy, és utána azzal tudsz neki üzengetni.
If your game idea starts with the story it’s not a game idea.
Stories in games are optional.
   
Tunyu - Tag | 447 hsz       Online status #208048   2015.08.05 23:42 GMT+1 óra  
Ha én egy ilyen

[url]https://msdn.microsoft.com/en-us/library/system.security.cryptography.rc2cryptoserviceprovider.generatekey(v=vs.110).aspx[/url]

kóddal generálok egy 128 bites kulcsot, akkor csak azon a gépen lehet ugyan azt a kulcsot generálni és visszafejteni!? Vagy hogy működik ez?

   
Instalok - Tag | 532 hsz       Online status #207922   2015.07.07 07:58 GMT+1 óra  
A cél valami hasonló rendszer kialakítása lett volna, azaz automatikus kód-generálás compile-time. Mint a lentebbi példában, a felső kódot megírom, az alsót pedig generálja fordítás előtt, és úgy fordítja le a kódot.

   
zbalai - Tag | 50 hsz       Online status #207913   2015.07.06 20:40 GMT+1 óra  
instalok:
OK, bocs.
És mit szeretnél elérni?

   
Instalok - Tag | 532 hsz       Online status #207912   2015.07.06 20:23 GMT+1 óra  
Kódgenerálás != property írás. Tudom mi az a property, köszi.

   
zbalai - Tag | 50 hsz       Online status #207911   2015.07.06 19:13 GMT+1 óra  
Te is tudsz property-ket csinálni természetesen.
Mit szeretnél pontosan?

https://msdn.microsoft.com/en-us/library/x9fsa0sw.aspx

   
Instalok - Tag | 532 hsz       Online status #207903   2015.07.06 16:29 GMT+1 óra  
Kicsit turkáltam a Unity assemblyt, és úgy láttam, hogy elég sok kódot generál. Ott van például a SyncVarAttribute. Ha ezzel meg van jelölve egy változó, akkor compile-time készít hozzá egy property-t, és minden egyes változó értékadást lecseréli erre a propertyre. Például:
Kód:
[SyncVar]
public float alma;

void Foo()
{
    alma = 10;
}

Ebből generál valami ilyesmit:
Kód:
[SyncVar]
public float alma;

public float Network_alma
{
    get { return alma; }
    set { UpdateSyncVar(value, alma); }
}

void Foo()
{
    Network_alma = 10;
}

Egyszerű halandó emberek is tudnak ilyet csinálni, vagy nem igazán éri meg az erőfeszítést?

   
Parallax - Tag | 574 hsz       Online status #206813   2015.03.02 10:10 GMT+1 óra  
Unity C# script 25 év programozás után valóban nagyon hárdkór. Legközelebb a Game Maker scripttel fogja megváltani a világot.

   
mash - Tag | 3 hsz       Online status #206808   2015.03.02 09:20 GMT+1 óra  
23 éve volt az, nem 25 és a Ray of Hope 2-ben te csak két effektet csináltál, a nagy része Aventage munkája. De azóta sem jött tőled semmi értékelhető dolog, ami érdekelné az embereket. Csináltál pár toolt, amit jóformán senki nem használ és három teljesen játszhatatlan játékot.
Közben meg ilyen hülyeségeket állítasz magadról, hogy te vagy a legjobb!

Idézet
versio :
asylium: ez 25 eves , es te meg ennyit se birsz felmutatni, ugyhogy van minimum 25 ev elonyom

ruhellem amikor a lamerok adogatnak




   
Asylum - Törzstag | 5441 hsz       Online status #206001   2015.01.03 16:32 GMT+1 óra  
Ki is tart el téged versi?
C++ fordítóval és macival alszom
http://darthasylum.blog.hu/
   
versio - Tag | 659 hsz       Online status #206000   2015.01.03 15:46 GMT+1 óra  
asylium: ez 25 eves , es te meg ennyit se birsz felmutatni, ugyhogy van minimum 25 ev elonyom

ruhellem amikor a lamerok adogatnak

   
Korábbi postok
> 1 < [2] [3] [4] [5] [6] [7] [8] [9] [10] [15] [20] [25] [30] [35] [40] [45] [46]