Click here to Skip to main content
15,889,909 members
Articles / Hosted Services / Azure

Linked Object Oriented Programming (POOV)

Rate me:
Please Sign up or sign in to vote.
4.69/5 (18 votes)
27 Oct 2016CPOL6 min read 25K   13   7
POOV is a programming technique for object-oriented languages developed in MIRA Software Factory by Ing. Eduardo Mireles and experts programmers. It facilitates coding software solutions.

Introduction

Linked Object Oriented Programming (POOV)

WHAT IS POOV?

POOV is a programming technique for object-oriented languages developed in MIRA Software Factory by Ing. Eduardo Mireles and experts programmers.

  • It facilitates coding software solutions.
  • It gives greater stability and ease of maintenance codes.
  • Effectively enables compliance with deadlines and costs.
  • Reduces failures and risks.

Facilitates coding software solutions

A major problem in using object-oriented languages is that you can not get its full potential because the most widely used databases are relational, which differs to an object-oriented technique.

POOV tries to get the full potential of OOP and adds the facility to store the state of objects in relational databases, hence OOP should make a small deviation and guide the programming to the "Linking" of objects, giving POOV result.

WHAT HAPPENS TO OOP?

  • It is difficult to model in detail with UML.
  • Usually at the end does not match the model with the code.
  • The classes end up having different methods than those referred to in the model.
  • Logic, definition and functionality of methods depends greatly on the style of the programmer.
  • It is more complicated to save the state of objects in relational databases or data code is oriented to data management.
  • The same business rules may be included in different classes.

WHAT HAPPENS WITH POOV?

  • It is easy to model in detail to the lines of code with UML.
  • The code is generated and attached to the model.
  • Code structure perfectly.
  • Logic, definition and functionality of the methods is predefined and adheres to the analysis.
  • The state of the objects is fully compatible to keep in relational databases.
  • The owners of the business rules are clearly identified.
  • A standardized regardless of style programmer code is generated.

POOV proposes to focus the code to:

  • Specialize in maintaining the persistence of objects and their recovery.
  • Specialize in the types of links, rules and behaviors.
  • Maintain specialized structures to provide these features.

For this POOV it has 2 specialized interfaces:

  1. An interface that provides functionality to himself Interface (Base Interface).
  2. An interface that provides functionality to other types of objects (Linked Interface).

1.- PERSISTENCE

All objects in a system must ensure their persistence and power have a way to recover.
For this POOV proposes a generic interface for all classes that would ensure this.

The Base Interface manages the persistence of objects of a class and its methods have several features and specialties.

  • Mapping features are: ID, IsDetached, PersistentState, Accepted, Hash and Schema.
  • Methods builders: NewObject, Initialize, Clone, Reset, Refresh, Restore, and builders and Dispose own class destroyers.
  • Updaters methods: Add, Update, Delete, AcceptChanges, RejectChanges, ValidateAdd, ValidateUpdate and ValidateDelete.
  • Selection methods: Select, FreeSelect, Find and Exist.
  • Transfer methods: Get, Set, Notify, Quiet and ToString.
  • Comparators methods: Equals, Same and CompareTo.

With this interface Base is enough to secure and manage the persistence of any object of any kind, no more is necessary.

The Base Interface ensures the persistence of objects of any kind, this interface is called CCB (Control Class Base).

Image 1

The purpose of a CCB is to standardize the management of persistence.
(For example, whether an object is of the Loan, Invoice or Product class persistence is administered in the same way)

Example:

New Loan:

NewLoan = Loan.NewObject();
NewLoan.Account = 5803;
NewLoan.Bank = "National";
NewLoan.Amount = 15000;
NewLoan.Add();
NewLoan.AcceptChanges();

Change Loan:

MyLoan = Loan.Find(5803);
MyLoan.Payment = 1000;
MyLoan.Update();
MyLoan.AcceptChanges();

Search Loan:

MyLoans[] = Loan.Select("National");

New Invoice:

NewInvoice = Invoice.NewObject();
NewInvoice.Number = 5803;
NewInvoice.Customer = "ABC Store";
NewInvoice.Amount = 376.25;
NewInvoice.Add();
NewInvoice.AcceptChanges();

Change Invoice:

MyInvoice = Invoice.Find(5803);
MyInvoice.Payment = 150;
MyInvoice.Update();
MyInvoice.AcceptChanges();

Search Invoice:

CustInvoices [] = Invoice.Select("ABC Store");

New Product:

NewProduct = Product.NewObject();
NewProduct.Code = "RD-671";
NewProduct.Name = "Solar Panel 260 Watts";
NewProduct.Price = 280;
NewProduct.Add();
NewProduct.AcceptChanges();

Change Product:

MyProduct = Product.Find("RD-671");
MyProduct.Price = 259.99;
MyProduct.Update();
MyProduct.AcceptChanges();

Search Product:

ListProducts[] = Product.Select();

All objects need to be born, update, search and delete. CCB provides the interface so that it can be performed in a standardized manner.

Note: What is being shown is the functionality of the CCB interface, the characteristics of the classes could be more or differnt.

2.- LINKS

In POOV there are 10 different types of links divided into 3 groups depending on their functionality:

  1. Qualifiers: Simple Qualifier (CS), Qualifier Composition (CC) and Qualifier Independent (CI).
  2. Relations: Simple Ratio (RS) Composition Ratio (RC), Historic Ratio (RH), Involution Ratio (RI).
  3. Joins: Simple Join (JS) Qualified Join Unique (JU) and Qualified Join Multiple (JM).

Be the Linked Interface manages the relationship of objects of two classes in a dependency Parent-Child and has 2 parts, the side of the Parent (P) and the side of the Child (H).

Methods Link P (Parent) are:

  • Link, Contain, Remove, Replace, LinkedClassName, ValidateLink, ValidateRemove.
  • Update, AcceptChanges, RejectChanges.

Methods Link H (Child) are:

  • NewObject, Find, Exist, Select.
  • Compute, Avg, Count, Max, Min, Sum (let you better performance calculations).

Apart from these methods, the H Link interface has an added feature that contains the parent object.

Example of a RC link type (Composition Ratio).

Image 2

The RC link has 2 parts, a RCP which should give functionality to the Parent and gives the functionality RCH to the Child so that the link can operate.

The purpose of be the Linked Interface is to standardize the management of relations between classes.
For example, whether a link is between InputOutput and Kardex class or between Item and Invoice or between Invoice and Payments, the linking is administered in the same way.

Example:

New Sales:

MyKardex = Kardex.Find("RD-671");


OutSale = InputOutput.NewObject();
OutSale.Quantity= 3;
OutSale.IO = "Output";

MyKardex.Link(OutSale);
MyKardex.Update();
MyKardex.AcceptChanges();

Kardex detail:

IOs[] = MyKardex.LinkedInputOutput ();

New Invoice Item:

MyInvoice = Invoice.Find(5803);


NewItem = InvoiceItem.NewObject();
NewItem.Cant = 3;
NewItem.Product = "Solar Panel 260 Watts";

MyInvoice.Link(NewItem);
MyInvoice.Update();
MyInvoice.AcceptChanges();

Invoice detail:

InvoiceDetail[] = MyInvoice.LinkedInvoiceItem();

New Invoice payment:

MyInvoice = Invoice.Find(5803);

NewPay = Payments.NewObject();
NewPay.Amount = 75.80;
NewPay.Date = "11/06/2015";

MyInvoice.Link(NewPay);
MyInvoice.Update();
MyInvoice.AcceptChanges();

Invoice detail:

InvoicePays[] = MyInvoice.LinkedPayments();

All links require join, removed, replaced and know the parent and childs.
Linked Interface provides the interface so that it can be performed in a standardized manner.

Note: What is being shown is the functionality of the Linked Interface, the characteristics of the classes could be more or differnt.

EASES CODING

  • POOV already has many of features and methods well defined in its functionality that allow any software development, and not required anymore.
  • POOV also has a well-defined regions and sub regions specialized code structure.
  • Allows the creation Snippets of specialized and reusable code.

A Snippet is a piece of code that can be reused.
POOV promotes the use of Snippets and defines much of these so that they can generate solutions based on join pieces of code previously tested.

Image 3

POOV models and specifies each link and the Snippet that will give functionality.
Thus, the Cliente (Customer) class would be encoded with a CCB Snippet which would be added 3 Property Str Snippets, a CCH Snippet, another CSP and one RSP Snippet.

For example, to encode the link between Factura (Invoice) and Partida (Items) it would:

  1. Snippet CCB is used to build the Invoice class (persistence functionality).
  2. Snippet of properties (DateTime, Int, Curr, Str, etc.) are used to add each of the features to the Invoice.
  3. Steps 1 and 2 are repeated but to encode Item class.
  4. In the Links Region of Invoice class sticks RCP Snippet that link with Item class.
  5. In the Links Region of Item class sticks RCH Snippet that link with the Invoice class.

Image 4

And ready.

Example of a Snippet of property String in C # for Visual Studio.

/// <summary>
/// Obtiene o establece $Descripcion$
/// </summary>
    public string $PropertyName$
    {
        get
        {
            if (this.cObj.IsNull["$MPName$"])
            { return string.Empty; }
            else
            { return (string)this.cObj["$MPName$"]; }
        }
        set
        {
            // if (value.Equals(string.Empty)) throw new Exception("El valor de $PropertyName$ no puede ser cadena nula.");
            if (value.Length > $Length$) { throw new Exception("$PropertyName$ debe tener un máximo de $Length$ caracteres."); }
            this.cObj["$MPName$"] = value;
        }

        // ToDo Copie y cotre la siguiente línea y péguela la región "Propiedades" del método Initializes.
        lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "$MPName$", "$FieldName$", typeof(System.String), $Length$));

        // ToDo Copie y cotre la siguiente linea y péguela en la Interfaz de la clase.
        string $PropertyName$ { get; set; }

        // ToDo Copie y cotre la siguiente linea y péguela en el método Get.
        pData.$PropertyName$ = this.$PropertyName$;

        // ToDo Copie y cotre la siguiente linea y péguela en el método Set.
        this.$PropertyName$ = pData.$PropertyName$;

    }

With POOV generate code is to joining Snippets, which have already been tested in multiple developments.
For the end attached to an application model, robust, stable and flawless.

EASE OF MAINTENANCE

As POOV has a well-defined and divided into regions and sub regions structure, any change, improvement or defect is fully localizable and estimable impact.
 

Image 5

This makes it far easier maintenance and generation of new versions.

DEADLINES AND COST EFFECTIVENESS

As POOV generates code assembling pieces and model they all parts are defined that accurately quantifies:

  • Encoding time.
  • Costs.
  • Progress.
  • Changes.

REDUCE FAULTS AND RISKS

Using proven Snippet to encode the risk of failure is reduced in the code and to be the model validated by customer and developer under POOV analysis practices the risks of inaccuracies and misunderstandings are reduced thereby generating effective applications that provide solutions to the requirements.

POOV is by far a programming technique that will help develop better code.

PPT document in spanish https://1drv.ms/p/s!Aotgp_wzjDaZgawTGcq8poOY3newaA

Contact: capacita@poov.mx  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer MIRA
Mexico Mexico
Mireles Applications Software Factory
ADAX & POOV

Comments and Discussions

 
QuestionPOOV: is most similar to the technique used an orm of type active record Pin
AMC12-Feb-17 13:28
AMC12-Feb-17 13:28 
AnswerMessage Closed Pin
3-Apr-17 11:28
Eduardo Mireles3-Apr-17 11:28 
AnswerRe: POOV: is most similar to the technique used an orm of type active record Pin
Eduardo Mireles4-Apr-17 11:15
Eduardo Mireles4-Apr-17 11:15 
PraiseRe: POOV: is most similar to the technique used an orm of type active record Pin
AMC7-Feb-18 8:01
AMC7-Feb-18 8:01 
GeneralRe: POOV: is most similar to the technique used an orm of type active record Pin
Eduardo Mireles29-Jan-19 10:49
Eduardo Mireles29-Jan-19 10:49 
GeneralRe: POOV: is most similar to the technique used an orm of type active record Pin
Eduardo Mireles29-Jan-19 19:42
Eduardo Mireles29-Jan-19 19:42 
This is a CCB class (Basic Control Class)
Representa una cámara de video y se apoya en VLC librerías.

MIRA.Data es nuestro ORM
MIRA.Data.SerializeObject en un registro.
MIRA:Data.TypeObject es una tabla de la base de datos.

La CCB controla la lógica de negocio de cada registro de la base de datos.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MIRA.Video
{
///
/// Representa una cámara de video.
///

public class Media
{
// Código elaborado por: Eduardo Mireles M.
// Fecha: 09/01/2019 Versión: 1.0
// Esquema: Video

#region State Variables and Attributes
#region Sección de Atributos
private static MIRA.Data.TypeObject cMyTypeObject;
private const string cMyBDName = "Video";
private MIRA.Data.SerializeObject cObj;
private System.Collections.Generic.List<mira.video.imedianotify> cNotify = null;

private Declarations.IMediaPlayerFactory cFactory;
private Declarations.Media.IMedia cMedia;
private Declarations.Players.IVideoPlayer cPlayer;
private Declarations.IMemoryRenderer cRender;
private Declarations.NewFrameEventHandler cNewFrame;

public delegate void delChange(MIRA.Video.Media sender, MIRA.Data.ChangeEventArgs e);
public delegate void delLink(MIRA.Video.Media sender, MIRA.Data.LinkEventArgs e);
public delegate void delQuestion(MIRA.Video.Media sender, MIRA.Data.QuestionEventArgs e);
public delegate void delNewFrame(MIRA.Video.Media sender, MIRA.Video.NewFrameEventArgs e);
public delegate void delError(object sender, System.Exception e);

///
/// Se produce cuando hay un nuevo frame de video.
///

public event delNewFrame NewFrame;
///
/// Se produce al haber un error en la secuencia de video.
///

public event delError OnError;
///
/// Se produce cuando ocurre un cambio de estado en un objeto Media.
///

public static event delChange Change;
///
/// Se produce cuando ocurre una vinculación entre Media y otro objeto.
///

public static event delLink Linking;
///
/// Ocurre cuando se requiere de información adicional en Media para ejecutar una acción.
///

public static event delQuestion Question;
#endregion

#region Sección de Variables de Estado

#endregion
#endregion

#region Assignments
///
/// Obtiene el identificador único de Media
///

public System.Guid ID
{ get { return this.cObj.ID; } }

///
/// Obtiene si la instancia forma parate de la colección de objetos válidos del sistema o no.
///

public Boolean IsDetached
{ get { return this.cObj.IsDetached; } }

///
/// Obtiene el estado del objeto persistente.
///

public System.Data.DataRowState PersistentState
{ get { return this.cObj.State; } }

///
/// Obtiene si el estado del objeto Media ya fue aceptado como válido o no.
///

public Boolean Accepted
{ get { return this.cObj.Accepted; } }

///
/// Obtiene el valor Hash del estado actual del objeto Media
///

public System.Guid Hash
{ get { return this.cObj.Hash; } }

///
/// Obtiene el nombre del esquema de datos al que pretenecen los objetos Media
///

public System.String Schema
{ get { return MIRA.Video.Media.cMyBDName; } }

///
/// Obtiene si el objeto proviene de la base de datos o no.
///

public bool IsPersistent
{ get { return this.cObj.IsPersistent; } }

///
/// Obtiene si el objeto ha cambiado desde su importación de la base de datos o el último AcceptChanges o RejectChanges.
///

public bool IsChanged
{ get { return this.cObj.IsChanged; } }
#endregion

#region Characteristics
///
/// Obtiene o establece el nombre de la cámara.
///

public string Name
{
get
{
if (this.cObj.IsNull["Nombre"])
{
return string.Empty;
}
else
{
return (string)this.cObj["Nombre"];
}
}
set
{
// Establezca la cadena de caracteres a validar.
string lDatos = "'";

// Valida el dato.
// if (value.Equals(string.Empty)) throw new Exception("El valor de Name no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Name.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Name.")); }
}
if (value.Length > 50) { throw new Exception("Name debe tener un máximo de 50 caracteres."); }

this.cObj["Nombre"] = value;
}
}

///
/// Obtiene o establece la descripción de la cámara.
///

public string Description
{
get
{
if (this.cObj.IsNull["Descrip"])
{
return string.Empty;
}
else
{
return (string)this.cObj["Descrip"];
}
}
set
{
// Establezca la cadena de caracteres a validar.
string lDatos = "'";

// Valida el dato.
// if (value.Equals(string.Empty)) throw new Exception("El valor de Description no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Description.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Description.")); }
}
if (value.Length > 250) { throw new Exception("Description debe tener un máximo de 250 caracteres."); }

this.cObj["Descrip"] = value;
}
}

///
/// Obtiene o establece el URL de la cámara.
///

public string URL
{
get
{
if (this.cObj.IsNull["URL"])
{
return string.Empty;
}
else
{
return (string)this.cObj["URL"];
}
}
set
{
// Establezca la cadena de caracteres a validar.
string lDatos = "'";

// Valida el dato.
// if (value.Equals(string.Empty)) throw new Exception("El valor de URL no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en URL.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en URL.")); }
}
if (value.Length > 512) { throw new Exception("URL debe tener un máximo de 512 caracteres."); }

this.cObj["URL"] = value;
}
}

///
/// Obtiene o establece el usuario de la cámara.
///

public string User
{
get
{
if (this.cObj.IsNull["Usuario"])
{
return string.Empty;
}
else
{
return (string)this.cObj["Usuario"];
}
}
set
{
// Establezca la cadena de caracteres a validar.
string lDatos = "'";

// Valida el dato.
// if (value.Equals(string.Empty)) throw new Exception("El valor de User no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en User.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en User.")); }
}
if (value.Length > 50) { throw new Exception("User debe tener un máximo de 50 caracteres."); }

this.cObj["Usuario"] = value;
}
}

///
/// Obtiene o establece la contraseña de la cámara.
///

public string Password
{
get
{
if (this.cObj.IsNull["Pass"])
{ return string.Empty;
}
else
{ return (string)this.cObj["Pass"];
}
}
set
{
// Establezca la cadena de caracteres a validar.
string lDatos = "'";

// Valida el dato.
// if (value.Equals(string.Empty)) throw new Exception("El valor de Password no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Password.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Password.")); }
}
if (value.Length > 50) { throw new Exception("Password debe tener un máximo de 50 caracteres."); }

this.cObj["Pass"] = value;
}
}

///
/// Obtiene el tamaño de las imágenes de Media.
///

public System.Drawing.Size Size
{
get
{
if (this.cPlayer == null)
return new System.Drawing.Size();
else
return this.cPlayer.GetVideoSize(0);
}
}

///
/// Obtiene o establece el estado de Media.
///

public MIRA.Video.MediaStatus Status
{
get { if (this.cPlayer == null) { return MediaStatus.Stop; } else { return MediaStatus.Play; } }
set
{
if (!this.Status.Equals(value))
{
switch (value)
{
case MediaStatus.Error:
throw new Exception("El estado de Error es de solo lectura.");

case MediaStatus.Pause:
this.Pause();
break;

case MediaStatus.Play:
this.Play();
break;

case MediaStatus.Stop:
this.Stop();
break;
}
}
}
}
#endregion



#region Constructors
///
/// Crea una nueva instancia de la clase Media
///

/// <returns>Nueva instancia de la clase Media con valores por default.
public static MIRA.Video.Media NewObject()
{
MIRA.Video.Media lNewObj;
MIRA.Data.ChangeEventArgs e;

MIRA.Video.Media.Initialize();

lNewObj = new MIRA.Video.Media(MIRA.Data.SerializeObject.NewObject(MIRA.Video.Media.cMyTypeObject));
lNewObj.Reset();

if (MIRA.Video.Media.Change != null)
{
e = new MIRA.Data.ChangeEventArgs(MIRA.Data.ChengeType.NewObjet, true);
MIRA.Video.Media.Change(lNewObj, e);
if (e.Cancel)
{
lNewObj.cObj.RejectChanges();
throw new Exception("Operación para crear nuevo objeto Media cancelada por el usuario.");
}
}

return lNewObj;
}

///
/// Inicializa la clase Media en el sistema garantizando un repositorio para sus instancias.
///

private static void Initialize()
{
// Verifica la existencia del repositorio para la clase Media.
if (MIRA.Video.Media.cMyTypeObject == null)
{
lock (MIRA.Video.Media.cMyBDName)
{
if (MIRA.Video.Media.cMyTypeObject == null)
{
// Si no existe el repositorio, instancía la base de datos para agrgarlo.
MIRA.Data.DataBase lDB = new MIRA.Data.DataBase(MIRA.Video.Media.cMyBDName);

// Crea un nuevo repositorio para la clase Media.
// Solo puede existir un solo repositorio para cada clase, así que si el repositorio ya existe
// NewObject recupera el configurado actualmente en la base de datos.
MIRA.Data.TypeObject lTpObj = MIRA.Data.TypeObject.NewObject(lDB, typeof(MIRA.Video.Media));

// MIRA.Data.Property lProp;
// Establece las características de la clase Media.
#region Definición de "Atributos Vinculantes" de la clase Media

#endregion
#region Definición de Propiedades de la clase Media
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Nombre", "Nombre", typeof(System.String), 50));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Descrip", "Descrip", typeof(System.String), 250));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "URL", "URL", typeof(System.String), 512));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Usuario", "Usuario", typeof(System.String), 50));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Pass", "Pass", typeof(System.String), 50));

#endregion

// Actualiza los datos del repositorio para la clase Media.
if (lTpObj.IsDetached)
{ lTpObj.Add(); }
else
{ lTpObj.Update(); }

lTpObj.AcceptChanges();
MIRA.Video.Media.cMyTypeObject = lTpObj;
}
}
}
}

///
/// Crea una nueva instancia de la clase Media enlazada con el objeto serializado.
///

/// <param name="pRow" />Objeto serializado a enlazar con la nueva instancia de Media.
private Media(MIRA.Data.SerializeObject pRow)
{
this.cObj = pRow;
pRow.ControlObject = this;

this.cFactory = new Implementation.MediaPlayerFactory();
this.cNewFrame += new Declarations.NewFrameEventHandler(OnNewFrame);
}

///
/// Crea una copia exacta del objeto, solo el ID será diferente.
///

/// <returns>Copia de la instancia de la clase Media que NO FORMA PARTE de la colección de objetoas válidos
public MIRA.Video.Media Clone()
{
MIRA.Video.Media lClone;

lClone = new MIRA.Video.Media(this.cObj.Clone());

#region Región de "Vínculos CCH" para Clone

#endregion
#region Región de "Vínculos RCP" para Clone

#endregion
#region Región de "Vínculos RHH" para Clone

#endregion

return lClone;
}

///
/// Reinicia la instancia.
///

public void Reset()
{
#region Región de "Vínculos CCH" para Reset

#endregion
#region Región de "Vínculos RCP" para Reset

#endregion
#region Región de "Vínculos VJE" para Reset

#endregion
#region Región de "Vínculos VRI" para Reset

#endregion
#region Región de "Vínculos JSP" para Reset

#endregion
#region Región de "Vínculos JUP" para Reset

#endregion

this.cObj.Reset();
#region Valores por default de las características

#endregion

}

///
/// Recarga la instancia
///

public void Refresh()
{
#region Región de "Vínculos CCH" para Refresh

#endregion
#region Región de "Vínculos RCP" para Refresh

#endregion
#region Región de "Vínculos VJE" para Refresh

#endregion
#region Región de "Vínculos VRI" para Refresh

#endregion
#region Región de "Vínculos JSP" para Refresh

#endregion
#region Región de "Vínculos JUP" para Refresh

#endregion

this.cObj.Refresh();
}

///
/// Restablece el repositorio para Media y lo regresa al estado previo a la ejecución de Initialize.
///

public static void Restore()
{ MIRA.Video.Media.cMyTypeObject = null; }

///
/// Libera todos los recursos utilizados por la instancia.
///

public void Dispose()
{
#region Código de "Características de la Clase" para Dispose

#endregion

#region Región de "Vínculos CCH" para Dispose

#endregion
#region Región de "Vínculos RCP" para Dispose

#endregion
#region Región de "Vínculos RHP" para Dispose

#endregion
#region Región de "Vínculos RSP" para Dispose

#endregion
#region Región de "Vínculos VJE" para Dispose

#endregion
}

///
/// Destructor de la clase
///

~Media()
{ }
#endregion

#region Updaters
///
/// Garantiza que los cambios se guarden en el repositorio de persistencia, es comparable con el Commit de una conexión a base de datos.
///

public void AcceptChanges()
{
MIRA.Data.ChangeEventArgs e;

if (!this.cObj.Accepted) { throw new Exception("Los datos se han modificado, se requiere usar Add, Update o Delete antes de AcceptChanges."); }

#region Región de "Vínculos RCH" para AcceptChanges

#endregion
#region Región de "Vínculos RHP" para AcceptChanges

#endregion
#region Región de "Vínculos RHH" para AcceptChanges

#endregion
#region Región de "Vínculos JSH" para AcceptChanges

#endregion
#region Región de "Vínculos JUH" para AcceptChanges

#endregion

if (!this.cObj.State.Equals(System.Data.DataRowState.Deleted))
{
this.cObj.AcceptChanges();
if (MIRA.Video.Media.Change != null)
{
e = new MIRA.Data.ChangeEventArgs(MIRA.Data.ChengeType.AcceptChanges, false);
MIRA.Video.Media.Change(this, e);
}
}


#region Región de "Vínculos CCH" para AcceptChanges

#endregion
#region Región de "Vínculos RCP" para AcceptChanges

#endregion
#region Región de "Vínculos RSP" para AcceptChanges

#endregion
#region Región de "Vínculos RSH" para AcceptChanges

#endregion
#region Región de "Vínculos VJE" para AcceptChanges

#endregion
#region Región de "Vínculos VRI" para AcceptChanges

#endregion
#region Región de "Vínculos JSP" para AcceptChanges

#endregion
#region Región de "Vínculos JUP" para AcceptChanges

#endregion

if (this.cObj.State.Equals(System.Data.DataRowState.Deleted))
{
this.cObj.AcceptChanges();
if (MIRA.Video.Media.Change != null)
{
e = new MIRA.Data.ChangeEventArgs(MIRA.Data.ChengeType.AcceptChanges, false);
MIRA.Video.Media.Change(this, e);
}
}
}

///
/// Agrega la nueva instancia Media a la colección de objetos válidos para el sistema.
///

public void Add()
{
if (this.IsDetached || this.PersistentState.Equals(System.Data.DataRowState.Added))
{
MIRA.Data.ChangeEventArgs e;

this.ValidateAdd();

#region Código para sus acciones previas a Add.

#endregion

// Pegue en las regiones sigueintes los fragmentos de código de los vínculos correspondientes.
#region Región de "Vínculos RCP" para Add

#endregion
#region Región de "Vínculos RSP" para Add

#endregion
#region Región de "Vínculos RSH" para Add

#endregion
#region Región de "Vínculos VJE" para Add

#endregion
#region Región de "Vínculos VRI" para Add

#endregion


e = new MIRA.Data.ChangeEventArgs(MIRA.Data.ChengeType.Add, true);
if (MIRA.Video.Media.Change != null) { MIRA.Video.Media.Change(this, e); }
if (e.Cancel) throw new Exception("Operación de agregar Media cancelada por el usuario.");
this.cObj.Add();


#region Código para sus acciones posteriores a Add.

#endregion

#region Región de "Vínculos CCH" para Add

#endregion
#region Región de "Vínculos RCH" para Add

#endregion
#region Región de "Vínculos JSP" para Add

#endregion
#region Región de "Vínculos JUP" para Add

#endregion

}
else
{ this.Update(); }
}

///
/// Actualiza el estado del objeto Media.
///

public void Update()
{
if (this.IsDetached || this.PersistentState.Equals(System.Data.DataRowState.Added))
{ this.Add(); }
else
{
MIRA.Data.ChangeEventArgs e;

this.ValidateUpdate();

#region Código para sus acciones previas a Update.

#endregion

// Pegue en las regiones sigueintes los fragmentos de código de los vínculos correspondientes.
#region Región de "Vínculos RCP" para Update

#endregion
#region Región de "Vínculos RSP" para Update

#endregion
#region Región de "Vínculos RSH" para Update

#endregion
#region Región de "Vínculos VJE" para Update

#endregion
#region Región de "Vínculos VRI" para Update

#endregion


e = new MIRA.Data.ChangeEventArgs(MIRA.Data.ChengeType.Update, true);
if (MIRA.Video.Media.Change != null) { MIRA.Video.Media.Change(this, e); }
if (e.Cancel) throw new Exception("Operación de actualizar Media cancelada por el usuario.");
this.cObj.Update();


#region Código para sus acciones posteriores a Update.

#endregion

#region Región de "Vínculos CCH" para Update

#endregion
#region Región de "Vínculos RCH" para Update

#endregion
#region Región de "Vínculos JSP" para Update

#endregion
#region Región de "Vínculos JUP" para Update

#endregion
}
}

///
/// Elimina el objeto Media.
///

public void Delete()
{
if (!this.IsDetached)
{
MIRA.Data.ChangeEventArgs e;

this.ValidateDelete();

#region Código para sus acciones previas a Delete.

#endregion

// Pegue en las regiones sigueintes los fragmentos de código de los vínculos correspondientes.
#region Región de "Vínculos RCP" para Delete

#endregion
#region Región de "Vínculos RSP" para Delete

#endregion
#region Región de "Vínculos RSH" para Delete

#endregion
#region Región de "Vínculos RHP" para Delete

#endregion
#region Región de "Vínculos VJE" para Delete

#endregion
#region Región de "Vínculos VRI" para Delete

#endregion
#region Región de "Vínculos JSP" para Delete

#endregion
#region Región de "Vínculos JUP" para Delete

#endregion
#region Región de "Vínculos CCH" para Delete

#endregion


e = new MIRA.Data.ChangeEventArgs(MIRA.Data.ChengeType.Delete, true);
if (MIRA.Video.Media.Change != null) { MIRA.Video.Media.Change(this, e); }
if (e.Cancel) throw new Exception("Operación de eliminar Media cancelada por el usuario.");
this.cObj.Delete();


#region Código para sus acciones posteriores a Delete.

#endregion

#region Región de "Vínculos RHH" para Delete

#endregion
#region Región de "Vínculos JSH" para Delete

#endregion
#region Región de "Vínculos JUH" para Delete

#endregion
}
else
{
#region Región de "Vínculos RCH" para Delete

#endregion
}
}

///
/// Deshace los cambios realizados en el estado del objeto Media.
///

public void RejectChanges()
{
MIRA.Data.ChangeEventArgs e;

// Pegue en las regiones sigueintes los fragmentos de código de los vínculos correspondientes.
#region Código de "Variables de Estado" para RejectChanges

#endregion

#region Código para sus acciones previas a RejectChanges.

#endregion

#region Región de "Vínculos CCH" para RejectChanges

#endregion
#region Región de "Vínculos RCP" para RejectChanges

#endregion
#region Región de "Vínculos RHH" para RejectChanges

#endregion
#region Región de "Vínculos RSP" para RejectChanges

#endregion
#region Región de "Vínculos VJE" para RejectChanges

#endregion
#region Región de "Vínculos VRI" para RejectChanges

#endregion
#region Región de "Vínculos JSH" para RejectChanges

#endregion


e = new MIRA.Data.ChangeEventArgs(MIRA.Data.ChengeType.RejectChanges, true);
if (MIRA.Video.Media.Change != null) { MIRA.Video.Media.Change(this, e); }
if (e.Cancel) throw new Exception("Operación de deshacer cambios en Media cancelada por el usuario.");
this.cObj.RejectChanges();


#region Código para sus acciones posteriores a RejectChanges.

#endregion

#region Región de "Vínculos RCH" para RejectChanges

#endregion
#region Región de "Vínculos RSH" para RejectChanges

#endregion
#region Región de "Vínculos JSP" para RejectChanges

#endregion
#region Región de "Vínculos RCH" para RejectChanges

#endregion
#region Región de "Vínculos JUP" para RejectChanges

#endregion
#region Región de "Vínculos JUH" para RejectChanges

#endregion
}

///
/// Valida los datos de una nueva instancia de manera que pueda ser agregado a la colección de objetos Media válidos para el sistema. Es llamado por el método Add.
///

private void ValidateAdd()
{
#region Región de validaciones propias de la clase Media para aceptar la nueva instancia.

#endregion

#region Validaciones de "Vínculos RCH" para ValidateAdd.

#endregion
#region Validaciones de "Vínculos RSP" para ValidateAdd.

#endregion

this.ValidateUpdate();
}

///
/// Valida los datos de la instancia para ser modificado su estado. Es llamado por el método Update.
///

private void ValidateUpdate()
{
#region Región de validaciones propias de la clase Media para aceptar la actualización del estado.
if (this.Name.Equals("")) throw new Exception("Falta el nombre de la cámara.");
#endregion

#region Validaciones de "Vínculos RSP" para ValidateUpdate.

#endregion
#region Validaciones de "Vínculos RHH" para ValidateUpdate.

#endregion

#region Validaciones de "Vínculos JSH" para ValidateUpdate.

#endregion
#region Validaciones de "Vínculos JUH" para ValidateUpdate.

#endregion
}

///
/// Valida si se puede eliminar el objeto Media. Es llamado por el método Delete.
///

private void ValidateDelete()
{
#region Región de validaciones propias de la clase Media para aceptar la eliminación del objeto.

#endregion

#region Validaciones de "Vínculos CCP" para ValidateDelete.

#endregion
#region Validaciones de "Vínculos CSP" para ValidateDelete.

#endregion

}
#endregion

#region Selects
///
/// Selecciona todos los objetos Media válidos para el sistema.
///

/// <returns>Array de objetos Media
public static MIRA.Video.Media[] Select()
{
return MIRA.Video.Media.FreeSelect("", "Nombre");
}

///
/// Selecciona todos los objetos Media válidos para el sistema.
///

/// <param name="pState" />Estado persistente de los objetos Media
/// <returns>Array de objetos Media
public static MIRA.Video.Media[] Select(System.Data.DataRowState pState)
{
return MIRA.Video.Media.FreeSelect("", "Nombre", pState);
}

///
/// Obtiene la colección de objetos Media que cumplan con la condición.
///

/// <param name="pWhere" />Condición
/// <param name="pOrderBy" />Orden en que regresará los resultados
/// <returns>Array de objetos Media
/// <remarks>FreeSelect es usado solo por expertos, la cláusula pWhere debe estar en en términos de los campos de la base de datos al igual que pOrderBy.
public static MIRA.Video.Media[] FreeSelect(String pWhere, String pOrderBy)
{
return MIRA.Video.Media.FreeSelect(pWhere, pOrderBy, System.Data.DataRowState.Added | System.Data.DataRowState.Detached | System.Data.DataRowState.Modified | System.Data.DataRowState.Unchanged);
}

///
/// Obtiene la colección de objetos Media que cumplan con la condición.
///

/// <param name="pWhere" />Condición
/// <param name="pOrderBy" />Orden en que regresará los resultados
/// <param name="pState" />Estado persistente de los objetos Media
/// <returns>Array de objetos Media
/// <remarks>FreeSelect es usado solo por expertos, la cláusula pWhere debe estar en en términos de los campos de la base de datos al igual que pOrderBy.
public static MIRA.Video.Media[] FreeSelect(String pWhere, String pOrderBy, System.Data.DataRowState pState)
{
MIRA.Video.Media[] lThisObjs;
MIRA.Data.SerializeObject[] lSerObjs;

MIRA.Video.Media.Initialize();
lSerObjs = MIRA.Data.SerializeObject.Select(MIRA.Video.Media.cMyTypeObject, pWhere, pOrderBy, pState);

lThisObjs = new MIRA.Video.Media[lSerObjs.Length];
for (Int32 X = 0; X < lSerObjs.Length; X++)
{
if (lSerObjs[X].ControlObject == null)
lThisObjs[X] = new MIRA.Video.Media(lSerObjs[X]);
else
lThisObjs[X] = lSerObjs[X].ControlObject as MIRA.Video.Media;
}

return lThisObjs;

}

///
/// Obtiene de caché la colección de objetos Media que cumplan con la condición.
///

/// <param name="pWhere" />Condición
/// <param name="pOrderBy" />Orden en que regresará los resultados
/// <param name="pState" />Estado persistente en caché de los objetos Media
/// <returns>Array de objetos Media
/// <remarks>FreeSelect es usado solo por expertos, la cláusula pWhere debe estar en en términos de los campos de la base de datos al igual que pOrderBy.
public static MIRA.Video.Media[] FreeSelect(String pWhere, System.Data.DataViewRowState pState, String pOrderBy)
{
MIRA.Video.Media[] lThisObjs;
MIRA.Data.SerializeObject[] lSerObjs;

MIRA.Video.Media.Initialize();
lSerObjs = MIRA.Data.SerializeObject.Select(MIRA.Video.Media.cMyTypeObject, pWhere, pState, pOrderBy);

lThisObjs = new MIRA.Video.Media[lSerObjs.Length];
for (Int32 X = 0; X < lSerObjs.Length; X++)
{
if (lSerObjs[X].ControlObject == null)
lThisObjs[X] = new MIRA.Video.Media(lSerObjs[X]);
else
lThisObjs[X] = lSerObjs[X].ControlObject as MIRA.Video.Media;
}

return lThisObjs;

}

///
/// Busca y recupera el objeto Media identificado por el ID, si el objeto no existe regresa Null.
///

/// <param name="pID" />Identificador del objeto Media a buscar
/// <returns>Objeto Media o Null en caso de no existir.
public static MIRA.Video.Media Find(System.Guid pID)
{
MIRA.Video.Media.Initialize();

MIRA.Data.SerializeObject lObj = MIRA.Data.SerializeObject.Find(MIRA.Video.Media.cMyTypeObject, pID);

if (lObj != null)
{
if (lObj.ControlObject == null)
return new MIRA.Video.Media(lObj);
else
return lObj.ControlObject as MIRA.Video.Media;
}

return null;
}

///
/// Determina si el identificador se encuentra en la colección de objetos Media válidos o no.
///

/// <param name="pID" />Identificador del objeto Media
/// <returns>Verdadero en caso de sí existir el objeto Media, Falso en caso contrario.
public static Boolean Exist(System.Guid pID)
{
MIRA.Video.Media.Initialize();

return MIRA.Data.SerializeObject.Exist(MIRA.Video.Media.cMyTypeObject, pID);
}
#endregion

#region Copiers
///
/// Toma los datos de esta instancia Media y los copia en la interfaz proporcionada.
///

/// <param name="pData" />Interfaz destino
public void Get(MIRA.Video.iMedia pData)
{
pData.Name = this.Name;
pData.Description = this.Description;
pData.URL = this.URL;
pData.User = this.User;
pData.Password = this.Password;

}

///
/// Toma los datos de la interfaz proporcionada y los copia en esta instancia Media.
///

/// <param name="pData" />Interfaz origen de los datos
public void Set(MIRA.Video.iMedia pData)
{
this.Name = pData.Name;
this.Description = pData.Description;
this.URL = pData.URL;
this.User = pData.User;
this.Password = pData.Password;

}

///
/// Devuelve un valor String representativo de Media que permita reconocerlo.
///

/// <returns>Cadena con la información representativa de esta instancia.
public override String ToString()
{
return String.Concat(this.Name);
}

///
/// Establece la interfaz que debe ser notificada de los eventos ocurridos en Media.
///

/// <param name="pData" />Interfaz a notificarle los eventos.
public void Notify(MIRA.Video.iMediaNotify pData)
{
if (this.cNotify == null) { this.cNotify = new System.Collections.Generic.List<mira.video.imedianotify>(); }
if (!this.cNotify.Contains(pData)) { this.cNotify.Add(pData); }
}

///
/// Desactiva la interfaz que era notificada por los eventos ocurridos en Media.
///

/// <param name="pData" />Interfaz a desactivar los eventos.
public void Quiet(MIRA.Video.iMediaNotify pData)
{
if (this.cNotify == null) { this.cNotify = new System.Collections.Generic.List<mira.video.imedianotify>(); }
if (this.cNotify.Contains(pData)) { this.cNotify.Remove(pData); }
}
#endregion

#region Comparers
///
/// Compara dos instancias de Media.
///

/// <param name="pMedia" />Objeto Media a comparar con esta instancia
/// <returns>Verdadero si las instancias son del mismo valor, Falso en caso contrario.
public bool Equals(MIRA.Video.Media pMedia)
{
return this.cObj.Equals(pMedia.cObj);
}

///
/// Determina si esta instancia y la pasada como argumento representan al mismo objeto.
///

/// <param name="pMedia" />Objeto a verificar
/// <returns>Verdadero si las instancias son del mismo objeto, falso en caso contrario.
public bool Same(MIRA.Video.Media pMedia)
{
return this.cObj.Same(pMedia.cObj);
}

///
/// Compara dos instancias de la clase Media.
///

/// <param name="pMedia" />Objeto Media a comparar con esta instancia
/// <returns>1 si esta instancia es mayor a pMedia, 0 si son iguales y -1 si esta instancia es menor que pMedia
public int CompareTo(MIRA.Video.Media pMedia)
{
// No todas las clases requeiren de implementar el método CompareTo
// Solo en el caso de que Media lo requiera comentarize la línea
// e implemente el código de comparación.
return this.ToString().CompareTo(pMedia.ToString());
}
#endregion

#region Links
#endregion

#region Calculates
#endregion

#region Notifications
#endregion

#region Methods
private void OnNewFrame(System.Drawing.Bitmap pNewFrame)
{
System.Threading.Monitor.Enter(this);

try
{
if (this.cPlayer != null)
{
if (this.NewFrame != null) this.NewFrame.Invoke(this, new MIRA.Video.NewFrameEventArgs(pNewFrame));
}
}
catch (Exception ex)
{ if (this.OnError != null) this.OnError.Invoke(this, ex); }

System.Threading.Monitor.Exit(this);
}

void Events_PlayerBuffering(object sender, EventArgs e)
{

}

void Events_PlayerSnapshotTaken(object sender, Declarations.Events.MediaPlayerSnapshotTaken e)
{
//throw new NotImplementedException();
}

void Events_ParsedChanged(object sender, Declarations.Events.MediaParseChange e)
{
//throw new NotImplementedException();
}

void Events_PlayerEncounteredError(object sender, EventArgs e)
{
if (this.OnError != null) this.OnError.Invoke(sender, new Exception("Error en la comunicación con la cámara."));
}

private void Play()
{
try
{
this.cMedia = this.cFactory.CreateMedia<declarations.media.imedia>(this.GetURL());
this.cMedia.Events.ParsedChanged += Events_ParsedChanged;

this.cPlayer = this.cFactory.CreatePlayer<declarations.players.ivideoplayer>();
this.cPlayer.Events.PlayerEncounteredError += Events_PlayerEncounteredError;
this.cPlayer.Events.PlayerSnapshotTaken += Events_PlayerSnapshotTaken;
this.cPlayer.Events.PlayerBuffering += Events_PlayerBuffering;
this.cPlayer.Open(this.cMedia);

this.cRender = this.cPlayer.CustomRenderer;
this.cRender.SetCallback(this.cNewFrame);
this.cRender.SetFormat(new Declarations.BitmapFormat(640, 480, Declarations.ChromaType.RV24)); // Declarations.ChromaType.RV24

this.cPlayer.Play();
}
catch (Exception ex)
{ if (this.OnError != null) this.OnError.Invoke(this, ex); }
}

private void Stop()
{
System.Threading.Monitor.Enter(this);
//this.cPlayer.Pause();

//while (this.cProcessingFrame) { System.Threading.Thread.Sleep(100); }
//this.cPlayer.Stop();

//this.cPlayer.Stop();

if (this.cRender != null)
{
this.cRender.SetCallback(null);
System.Threading.Thread.Sleep(100);
this.cRender.Dispose();
this.cRender = null;
}

this.cPlayer.Stop();

this.cPlayer.Dispose();
this.cMedia.Dispose();

this.cPlayer = null;
this.cMedia = null;
this.cRender = null;

System.Threading.Monitor.Exit(this);
}

private void Pause()
{
System.Threading.Monitor.Enter(this);
this.cPlayer.Pause();
System.Threading.Monitor.Exit(this);
}

private string GetURL()
{
string lURL = "";
System.Uri lURI;

if (this.URL.Equals("")) throw new Exception("Falta la dirección URL de la cámara.");

lURI = new System.Uri(this.URL);
lURL = string.Concat(lURI.Scheme, "://");

if (this.User.Equals("") && this.Password.Equals(""))
lURL = this.URL;
else
lURL = string.Concat(lURI.Scheme, "://", this.User, ":", this.Password, "@", lURI.Host, ":", lURI.Port.ToString(), lURI.AbsolutePath);

return lURL;
}
#endregion
}



///
/// Lista el estado funcional de una cámara
///

public enum MediaStatus
{
///
/// El proceso está detenido.
///

Stop = 1,
///
/// El proceso está en ejecución.
///

Play = 2,
///
/// El proceso está pausado.
///

Pause = 3,
///
/// Ocurrió un error en la cámara.
///

Error = 4
}



///
/// Interfaz que deberán implementar las clases que deban ser notificadas de eventos en Media.
///

public interface iMediaNotify
{

}



///
/// Interfaz que deberán implementar las clases que intercambien datos con Media.
///

public interface iMedia
{
string Name { get; set; }
string Description { get; set; }
string URL { get; set; }
string User { get; set; }
string Password { get; set; }

}



///
/// Representa los argumentos de un evento de nuevo frame.
///

public class NewFrameEventArgs : System.EventArgs
{
private System.Drawing.Bitmap p_Frame;

///
/// Obtiene el frame obtenido de la secuencia de video.
///

public System.Drawing.Bitmap Frame
{
get { return this.p_Frame; }
}

internal NewFrameEventArgs(System.Drawing.Bitmap pFrame)
{
this.p_Frame = new System.Drawing.Bitmap(pFrame);
}
}
}



This other CCB represents a scale for weighing trucks.

The structure is the same as the video camera but it does something very different.

The public methods are the same, those of the video camera and those of the Scale, however, they do very different things.

Here the interesting thing is that there is an interface common to all the classes that may exist in a system.
Add, Update, Remove, Delete, Link, Select, Find, etc. they live and work the same in all the classes of the system and it does not matter if it is a video camera or a truck scale.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ICI.Bascula.Ctrl
{
///
/// Representa una báscula
///

public class Bascula
{
// Código elaborado por: Eduardo Mireles M.
// Fecha: 14/07/2017 Versión: 1.0
// Esquema: ICI_Bascula

#region State Variables and Attributes
#region Sección de Atributos
private static MIRA.Data.TypeObject cMyTypeObject;
private const string cMyBDName = "ICI_Bascula";
private MIRA.Data.SerializeObject cObj;
private System.Collections.Generic.List<ici.bascula.ctrl.ibasculanotify> cNotify = null;

private System.IO.Ports.SerialPort cSerial;
private System.Net.Sockets.NetworkStream cBuffer;
private System.Threading.Thread cProcContinuo;
private System.Timers.Timer cTimer;
private string cComandoPeticion = "";
private DateTime cSiguientePeso;
#endregion

#region Sección de Variables de Estado
private ICI.Bascula.Ctrl.BasculaStatus p_Status = BasculaStatus.Apagado;
private System.Exception p_Error = null;
private string p_Peso = "";
private Single p_PesoNum = 0;
private MIRA.Video.Media p_CamaraFrontal, p_CamaraSuperior, p_CamaraTrasera;

#endregion
#endregion

#region Assignments
///
/// Obtiene el identificador único de Bascula
///

public System.Guid ID
{ get { return this.cObj.ID; } }

///
/// Obtiene si la instancia forma parate de la colección de objetos válidos del sistema o no.
///

public Boolean IsDetached
{ get { return this.cObj.IsDetached; } }

///
/// Obtiene el estado del objeto persistente.
///

public System.Data.DataRowState PersistentState
{ get { return this.cObj.State; } }

///
/// Obtiene si el estado del objeto Bascula ya fue aceptado como válido o no.
///

public Boolean Accepted
{ get { return this.cObj.Accepted; } }

///
/// Obtiene el valor Hash del estado actual del objeto Bascula
///

public System.Guid Hash
{ get { return this.cObj.Hash; } }

///
/// Obtiene el nombre del esquema de datos al que pretenecen los objetos Bascula
///

public System.String Schema
{ get { return ICI.Bascula.Ctrl.Bascula.cMyBDName; } }

///
/// Obtiene si el objeto ha cambiado desde su importación de la base de datos o el último AcceptChanges o RejectChanges.
///

public bool IsChanged
{ get { return this.cObj.IsChanged; } }
#endregion

#region Characteristics
///
/// Obtiene o establece el nombre de la báscula.
///

public string Nombre
{
get
{
if (this.cObj.IsNull["Nombre"])
{ return string.Empty; }
else
{ return (string)this.cObj["Nombre"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
string lDatos = "'";

// Valida el dato.
if (value.Equals(string.Empty)) throw new Exception("El valor de Nombre no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Nombre.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Nombre.")); }
}
if (value.Length > 50) { throw new Exception("Nombre debe tener un máximo de 50 caracteres."); }

this.cObj["Nombre"] = value;
}
}

///
/// Obtiene o establece el estado de la báscula.
///

public ICI.Bascula.Ctrl.BasculaStatus Status
{
get
{
switch (this.Comunicacion)
{
case Comunicacion.Ethernet:
break;

case Comunicacion.Serial:
if (this.cSerial == null) return BasculaStatus.Apagado;
if (this.cSerial.IsOpen)
return BasculaStatus.Encendido;
else
return BasculaStatus.Apagado;

case Comunicacion.Virtual:
if (this.cTimer.Enabled)
return BasculaStatus.Encendido;
else
return BasculaStatus.Apagado;
}

return this.p_Status;
}
set
{
if (!value.Equals(this.Status))
{
switch (value)
{
case BasculaStatus.Apagado:
switch (this.Comunicacion)
{
case Comunicacion.Ethernet:
this.ApagarIP();
break;

case Comunicacion.Serial:
this.ApagarComm();
break;

case Comunicacion.Virtual:
this.ApagarVirtual();
break;
}
break;

case BasculaStatus.Encendido:
switch (this.Comunicacion)
{
case Comunicacion.Ethernet:
this.EncenderIP();
break;

case Comunicacion.Serial:
this.EncenderComm();
break;

case Comunicacion.Virtual:
this.EncenderVirtual();
break;
}
break;

case BasculaStatus.Error:
throw new Exception("El estado de error no puede ser establecido directamente, es de solo lectura.");
}
}
}
}

///
/// Obtiene el error en caso de tener algun fallo en la conexión y/o comunicación con el hardware.
///

public System.Exception Error
{
get { return this.p_Error; }
}

///
/// Obtiene si en la báscula ha ocurrido un error.
///

public bool HasError
{ get { return this.Error == null ? false : true; } }

///
/// Obtiene o establece la unidad de peso (Kgs, Lbs, Tons, etc.).
///

public string Unidad
{
get
{
if (this.cObj.IsNull["Unidad"])
{ return "Kgs."; }
else
{ return (string)this.cObj["Unidad"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
string lDatos = "'";

// Valida el dato.
if (value.Equals(string.Empty)) throw new Exception("El valor de Unidad no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Unidad.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Unidad.")); }
}
if (value.Length > 5) { throw new Exception("Unidad debe tener un máximo de 5 caracteres."); }

this.cObj["Unidad"] = value;
}
}

///
/// Obtiene o establece la IP del hardware.
///

public string IP
{
get
{
if (this.cObj.IsNull["IP"])
{ return string.Empty; }
else
{ return (string)this.cObj["IP"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
string lDatos = "0123456789.";

// Valida el dato.
//if (value.Equals(string.Empty)) throw new Exception("El valor de IP no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en CadenaConexion.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
//if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en CadenaConexion.")); }
}
if (value.Length > 15) { throw new Exception("IP debe tener un máximo de 15 caracteres."); }

this.cObj["IP"] = value;
}
}

///
/// Obtiene o establece el medio de comunicación que la clase usará para intercambiar datos con el hardware.
///

public ICI.Bascula.Ctrl.Comunicacion Comunicacion
{
get
{
if (this.cObj.IsNull["Comunicacion"])
{ return ICI.Bascula.Ctrl.Comunicacion.Serial; }
else
{ return (ICI.Bascula.Ctrl.Comunicacion)(Int32)this.cObj["Comunicacion"]; }
}
set
{
this.cObj["Comunicacion"] = value;
}
}

///
/// Obtiene o establece el tipo de hardware donde se obtiene el peso.
///

public ICI.Bascula.Ctrl.Hardware Hardware
{
get
{
if (this.cObj.IsNull["Hardware"])
{ return ICI.Bascula.Ctrl.Hardware.Ricelake_920i; }
else
{ return (ICI.Bascula.Ctrl.Hardware)(Int32)this.cObj["Hardware"]; }
}
set
{
this.cObj["Hardware"] = value;
}
}

///
/// Obtiene o establece el sertificado de calibración.
///

public string Calibracion
{
get
{
if (this.cObj.IsNull["Calibracion"])
{ return string.Empty; }
else
{ return (string)this.cObj["Calibracion"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
//string lDatos = "abcdefghijklmnñopqrstuvwxyz ABCDEFGHIJKLMNÑOPQRSTUVWXYZ1234567890áéíóúÁÉÍÓÚüÜ.-()*+/#_:&";

// Valida el dato.
// if (value.Equals(string.Empty)) throw new Exception("El valor de Calibracion no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Calibracion.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
// if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Calibracion.")); }
}
if (value.Length > 15) { throw new Exception("Calibración debe tener un máximo de 15 caracteres."); }

this.cObj["Calibracion"] = value;
}
}

///
/// Obtiene o establece el certificado de instrumento.
///

public string Instrumento
{
get
{
if (this.cObj.IsNull["Instrumento"])
{ return string.Empty; }
else
{ return (string)this.cObj["Instrumento"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
//string lDatos = "abcdefghijklmnñopqrstuvwxyz ABCDEFGHIJKLMNÑOPQRSTUVWXYZ1234567890áéíóúÁÉÍÓÚüÜ.-()*+/#_:&";

// Valida el dato.
// if (value.Equals(string.Empty)) throw new Exception("El valor de Instrumento no puede ser cadena nula.");
foreach (char lChar in value.ToCharArray())
{
// Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Instrumento.")); }
// Use la siguiente línea si lDatos contiene caracteres NO válidos.
// if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Instrumento.")); }
}
if (value.Length > 15) { throw new Exception("Instrumento debe tener un máximo de 15 caracteres."); }

this.cObj["Instrumento"] = value;
}
}

///
/// Obtiene la cadena con el peso actual.
///

public string Peso
{
get
{
return this.p_Peso;
}
}

///
/// Obtiene el peso actual.
///

public Single PesoNum
{
get { return this.p_PesoNum; }
}

///
/// Obtiene o establece si la respuesta del hardware es continua o requiere de una petición de datos.
///

public bool Continuo
{
get
{
if (this.cObj.IsNull["Continuo"])
{ return false; }
else
{ return (bool)this.cObj["Continuo"]; }
}
set
{
this.cObj["Continuo"] = value;
}
}

///
/// Obtiene o establece el puerto IP o Comm de la conexión.
///

public int Puerto
{
get
{
if (this.cObj.IsNull["Puerto"])
{
switch (this.Comunicacion)
{
case Comunicacion.Ethernet:
return 10001;

case Comunicacion.Serial:
return 1;

default:
return -1;
}
}
else
{ return (int)this.cObj["Puerto"]; }
}
set
{
if (value < 0) { throw new Exception("El valor de Puerto no puede ser negativo."); }
this.cObj["Puerto"] = value;
}
}

///
/// Obtiene o establece la velocidad en baudios del puero Comm.
///

public int Baudios
{
get
{
if (this.cObj.IsNull["Baudios"])
{ return 9600; }
else
{ return (int)this.cObj["Baudios"]; }
}
set
{
if (value < 0) { throw new Exception("El valor de Baudios no puede ser negativo."); }
this.cObj["Baudios"] = value;
}
}

///
/// Obtiene o establece la paridad en los datos Comm.
///

public System.IO.Ports.Parity Paridad
{
get
{
if (this.cObj.IsNull["Paridad"])
{ return System.IO.Ports.Parity.None; }
else
{ return (System.IO.Ports.Parity)(Int32)this.cObj["Paridad"]; }
}
set
{
this.cObj["Paridad"] = value;
}
}

///
/// Obtiene o establece los bits de datos del puerto Comm.
///

public int BitsDatos
{
get
{
if (this.cObj.IsNull["BitsDatos"])
{ return 8; }
else
{ return (int)this.cObj["BitsDatos"]; }
}
set
{
if (value < 0) { throw new Exception("El valor de BitsDatos no puede ser negativo."); }
this.cObj["BitsDatos"] = value;
}
}

///
/// Obtiene o establece los bits de parada de datos Comm.
///

public System.IO.Ports.StopBits BitsParada
{
get
{
if (this.cObj.IsNull["BitsParada"])
{ return System.IO.Ports.StopBits.One; }
else
{ return (System.IO.Ports.StopBits)(Int32)this.cObj["BitsParada"]; }
}
set
{
this.cObj["BitsParada"] = value;
}
}

///
/// Obtiene o establece el control de flujo de datos Comm.
///

public System.IO.Ports.Handshake ControlFlujo
{
get
{
if (this.cObj.IsNull["ControlFlujo"])
{ return System.IO.Ports.Handshake.None; }
else
{ return (System.IO.Ports.Handshake)(Int32)this.cObj["ControlFlujo"]; }
}
set
{
this.cObj["ControlFlujo"] = value;
}
}

///
/// Obtiene o establece el comando a enviar al hardware para obtener el peso.
///

public string Peticion
{
get
{
if (this.cObj.IsNull["Peticion"])
{ return "<tx=xg#1><cr><lf>"; }
else
{ return (string)this.cObj["Peticion"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
//string lDatos = "";

// Valida el dato.
// if (value.Equals(string.Empty)) throw new Exception("El valor de Peticion no puede ser cadena nula.");
//foreach (char lChar in value.ToCharArray())
//{
// // Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// // if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Peticion.")); }
// // Use la siguiente línea si lDatos contiene caracteres NO válidos.
// // if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Peticion.")); }
//}
if (value.Length > 1024) { throw new Exception("Peticion debe tener un máximo de 1024 caracteres."); }

this.cComandoPeticion = "";
this.cObj["Peticion"] = value;
}
}

///
/// Obtiene o establece el comando recibido del hardware para obtener el peso.
///

public string Respuesta
{
get
{
if (this.cObj.IsNull["Respuesta"])
{ return "<stx><pol><w07><unit01><gn><o><cr>"; } // Peso: "\u0002 517.1LG \r"
else
{ return (string)this.cObj["Respuesta"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
//string lDatos = "abcdefghijklmnñopqrstuvwxyz ABCDEFGHIJKLMNÑOPQRSTUVWXYZ1234567890áéíóúÁÉÍÓÚüÜ.-()*+/#_:&";

//// Valida el dato.
//// if (value.Equals(string.Empty)) throw new Exception("El valor de Respuesta no puede ser cadena nula.");
//foreach (char lChar in value.ToCharArray())
//{
// // Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// // if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Respuesta.")); }
// // Use la siguiente línea si lDatos contiene caracteres NO válidos.
// // if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Respuesta.")); }
//}
if (value.Length > 1024) { throw new Exception("Respuesta debe tener un máximo de 1024 caracteres."); }

this.cObj["Respuesta"] = value;
}
}

///
/// Obtiene o establece el formato de salida del peso.
///

public string Formato
{
get
{
if (this.cObj.IsNull["Formato"])
{ return "#0.0"; }
else
{ return (string)this.cObj["Formato"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
//string lDatos = "abcdefghijklmnñopqrstuvwxyz ABCDEFGHIJKLMNÑOPQRSTUVWXYZ1234567890áéíóúÁÉÍÓÚüÜ.-()*+/#_:&";

//// Valida el dato.
//// if (value.Equals(string.Empty)) throw new Exception("El valor de Formato no puede ser cadena nula.");
//foreach (char lChar in value.ToCharArray())
//{
// // Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// // if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Formato.")); }
// // Use la siguiente línea si lDatos contiene caracteres NO válidos.
// // if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Formato.")); }
//}
if (value.Length > 15) { throw new Exception("Formato debe tener un máximo de 15 caracteres."); }

this.cObj["Formato"] = value;
}
}

///
/// Obtiene o establece la cadena que el hardware envía como indicador de desbordamiento máximo.
///

public string Overflow
{
get
{
if (this.cObj.IsNull["Overflow"])
{ return "<stx><sp01><ascii&07><tx=lgo><cr>"; } // Overflow: "\u0002 &&&&&&&LGO\r"
else
{ return (string)this.cObj["Overflow"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
//string lDatos = "abcdefghijklmnñopqrstuvwxyz ABCDEFGHIJKLMNÑOPQRSTUVWXYZ1234567890áéíóúÁÉÍÓÚüÜ.-()*+/#_:&";

//// Valida el dato.
//// if (value.Equals(string.Empty)) throw new Exception("El valor de Overflow no puede ser cadena nula.");
//foreach (char lChar in value.ToCharArray())
//{
// // Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// // if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Overflow.")); }
// // Use la siguiente línea si lDatos contiene caracteres NO válidos.
// // if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Overflow.")); }
//}
if (value.Length > 512) { throw new Exception("Overflow debe tener un máximo de 512 caracteres."); }

this.cObj["Overflow"] = value;
}
}

///
/// Obtiene o establece la cadena que el hardware envía como indicador de desbordamiento mínimo.
///

public string Underflow
{
get
{
if (this.cObj.IsNull["Underflow"])
{ return "<stx><ascii-><ascii=06><null><tx=lgo><cr>"; } // Underflow: "\u0002-======\0LGO\r"
else
{ return (string)this.cObj["Underflow"]; }
}
set
{
// Establezca la cadena de caracteres a validar.
//string lDatos = "abcdefghijklmnñopqrstuvwxyz ABCDEFGHIJKLMNÑOPQRSTUVWXYZ1234567890áéíóúÁÉÍÓÚüÜ.-()*+/#_:&";

//// Valida el dato.
//// if (value.Equals(string.Empty)) throw new Exception("El valor de Underflow no puede ser cadena nula.");
//foreach (char lChar in value.ToCharArray())
//{
// // Use la siguiente línea si lDatos contiene caracteres SÍ válidos.
// // if (lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Underflow.")); }
// // Use la siguiente línea si lDatos contiene caracteres NO válidos.
// // if (!lDatos.IndexOf(lChar).Equals(-1)) { throw new Exception(string.Concat("El caracter ", lChar.ToString(), " no es válido en Underflow.")); }
//}
if (value.Length > 512) { throw new Exception("Underflow debe tener un máximo de 512 caracteres."); }

this.cObj["Underflow"] = value;
}
}
#endregion



#region Constructors
///
/// Crea una nueva instancia de la clase Bascula
///

/// <returns>Nueva instancia de la clase Bascula con valores por default.
public static ICI.Bascula.Ctrl.Bascula NewObject()
{
ICI.Bascula.Ctrl.Bascula lNewObj;

ICI.Bascula.Ctrl.Bascula.Initialize();

lNewObj = new ICI.Bascula.Ctrl.Bascula();
lNewObj.cObj = MIRA.Data.SerializeObject.NewObject(ICI.Bascula.Ctrl.Bascula.cMyTypeObject);
lNewObj.Reset();

return lNewObj;

}

///
/// Inicializa la clase Bascula en el sistema garantizando un repositorio para sus instancias.
///

private static void Initialize()
{
// Verifica la existencia del repositorio para la clase Bascula.
if (ICI.Bascula.Ctrl.Bascula.cMyTypeObject == null)
{
lock (ICI.Bascula.Ctrl.Bascula.cMyBDName)
{
if (ICI.Bascula.Ctrl.Bascula.cMyTypeObject == null)
{
// Si no existe el repositorio, instancía la base de datos para agrgarlo.
MIRA.Data.DataBase lDB = new MIRA.Data.DataBase(ICI.Bascula.Ctrl.Bascula.cMyBDName);

// Crea un nuevo repositorio para la clase Bascula.
// Solo puede existir un solo repositorio para cada clase, así que si el repositorio ya existe
// NewObject recupera el configurado actualmente en la base de datos.
MIRA.Data.TypeObject lTpObj = MIRA.Data.TypeObject.NewObject(lDB, typeof(ICI.Bascula.Ctrl.Bascula));

// MIRA.Data.Property lProp;
// Establece las características de la clase Bascula.
#region Definición de "Atributos Vinculantes" de la clase Bascula
#region Atributo del vínculo CSH con Media
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "IdCamFront", typeof(System.Guid)));
#endregion
#region Atributo del vínculo CSH con Media
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "IdCamSup", typeof(System.Guid)));
#endregion
#region Atributo del vínculo CSH con Media
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "IdCamTras", typeof(System.Guid)));
#endregion

#endregion
#region Definición de Propiedades de la clase Bascula
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Nombre", "Nombre", typeof(System.String), 50));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Unidad", "Unidad", typeof(System.String), 5));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "IP", "IP", typeof(System.String), 15));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Comunicacion", typeof(System.Int32)));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Hardware", typeof(System.Int32)));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Calibracion", "Calibracion", typeof(System.String), 15));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Instrumento", "Instrumento", typeof(System.String), 15));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Continuo", typeof(System.Boolean)));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Puerto", typeof(System.Int32)));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Baudios", typeof(System.Int32)));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Paridad", typeof(System.Int32)));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "BitsDatos", typeof(System.Int32)));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "BitsParada", typeof(System.Int32)));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "ControlFlujo", typeof(System.Int32)));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Peticion", "Peticion", typeof(System.String), 1024));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Respuesta", "Respuesta", typeof(System.String), 1024));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Formato", "Formato", typeof(System.String), 15));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Overflow", "Overflow", typeof(System.String), 512));
lTpObj.Add(MIRA.Data.Property.NewObject(lTpObj, "Underflow", "Underflow", typeof(System.String), 512));

#endregion

// Actualiza los datos del repositorio para la clase Bascula.
if (lTpObj.IsDetached)
{ lTpObj.Add(); }
else
{ lTpObj.Update(); }

lTpObj.AcceptChanges();
ICI.Bascula.Ctrl.Bascula.cMyTypeObject = lTpObj;
}
}
}
}

///
/// Crea una instancia de la clase Bascula
///

/// <remarks>
/// El constructor sin parámetros de la clase debe ser privado.
/// Todas las nuevas instancias deberán ser obtenidas por medio de NewObject() o sus sobrecargas.
///
private Bascula()
{
this.cTimer = new System.Timers.Timer(1000);
this.cTimer.Elapsed += Timer_Elapsed;
}

///
/// Crea la instancia de Bascula correspondiente al ID
///

/// <param name="pID" />Identificador del objeto Bascula a instanciar
public Bascula(System.Guid pID)
{
ICI.Bascula.Ctrl.Bascula.Initialize();
this.cObj = MIRA.Data.SerializeObject.Find(ICI.Bascula.Ctrl.Bascula.cMyTypeObject, pID);
if (this.cObj == null) { throw new Exception(String.Concat("No se puede crear la instancia ", pID.ToString(), " de la clase ", this.GetType().Name, " porque no se encuentra en la base de datos.")); }

this.cTimer = new System.Timers.Timer(1000);
this.cTimer.Elapsed += Timer_Elapsed;
}

///
/// Crea una copia exacta del objeto, solo el ID será diferente.
///

/// <returns>Copia de la instancia de la clase Bascula que NO FORMA PARTE de la colección de objetoas válidos
public ICI.Bascula.Ctrl.Bascula Clone()
{
ICI.Bascula.Ctrl.Bascula lClone;

lClone = new ICI.Bascula.Ctrl.Bascula();
lClone.cObj = this.cObj.Clone();

#region Región de "Vínculos CCH" para Clone

#endregion
#region Región de "Vínculos RCP" para Clone

#endregion
#region Región de "Vínculos RHH" para Clone

#endregion

return lClone;
}

///
/// Reinicia la instancia.
///

public void Reset()
{
#region Región de "Vínculos CCH" para Reset

#endregion
#region Región de "Vínculos RCP" para Reset

#endregion
#region Región de "Vínculos VJE" para Reset

#endregion
#region Región de "Vínculos VRI" para Reset

#endregion
#region Región de "Vínculos JSP" para Reset

#endregion
#region Región de "Vínculos JUP" para Reset

#endregion

this.cObj.Reset();
#region Valores por default de las características
this.p_Error = null;
#endregion

}

///
/// Recarga la instancia
///

public void Refresh()
{
#region Región de "Vínculos CCH" para Refresh

#endregion
#region Región de "Vínculos RCP" para Refresh

#endregion
#region Región de "Vínculos VJE" para Refresh

#endregion
#region Región de "Vínculos VRI" para Refresh

#endregion
#region Región de "Vínculos JSP" para Refresh

#endregion
#region Región de "Vínculos JUP" para Refresh

#endregion

this.cObj.Refresh();
}

///
/// Restablece el repositorio para Bascula y lo regresa al estado previo a la ejecución de Initialize.
///

public static void Restore()
{ ICI.Bascula.Ctrl.Bascula.cMyTypeObject = null; }

///
/// Libera todos los recursos utilizados por la instancia.
///

public void Dispose()
{
#region Código de "Características de la Clase" para Dispose

#endregion

#region Región de "Vínculos CCH" para Dispose

#endregion
#region Región de "Vínculos RCP" para Dispose

#endregion
#region Región de "Vínculos RHP" para Dispose
#region Código del vínculo RHP con Pesaje.
foreach (ICI.Bascula.Ctrl.Pesaje lObjRCP in ICI.Bascula.Ctrl.Pesaje.Select(this, System.Data.DataRowState.Added | System.Data.DataRowState.Detached | System.Data.DataRowState.Deleted | System.Data.DataRowState.Modified | System.Data.DataRowState.Unchanged))
{
lObjRCP.Dispose();
}
#endregion

#endregion
#region Región de "Vínculos RSP" para Dispose

#endregion
#region Región de "Vínculos VJE" para Dispose

#endregion
}

///
/// Destructor de la clase
///

~Bascula()
{ }
#endregion

#region Updaters
///
/// Garantiza que los cambios se guarden en el repositorio de persistencia, es comparable con el Commit de una conexión a base de datos.
///

public void AcceptChanges()
{
if (!this.cObj.Accepted) { throw new Exception("Los datos se han modificado, se requiere usar Add, Update o Delete antes de AcceptChanges."); }

#region Región de "Vínculos RCH" para AcceptChanges

#endregion
#region Región de "Vínculos RHP" para AcceptChanges
#region Código del vínculo RHP con Pesaje.
if (this.cObj.State.Equals(System.Data.DataRowState.Deleted))
{
foreach (ICI.Bascula.Ctrl.Pesaje lLnkObj in ICI.Bascula.Ctrl.Pesaje.Select(this, System.Data.DataRowState.Added | System.Data.DataRowState.Detached | System.Data.DataRowState.Deleted | System.Data.DataRowState.Modified))
{
lLnkObj.AcceptChanges();
}
}
#endregion

#endregion
#region Región de "Vínculos RHH" para AcceptChanges

#endregion
#region Región de "Vínculos JSH" para AcceptChanges

#endregion
#region Región de "Vínculos JUH" para AcceptChanges

#endregion

if (!this.cObj.State.Equals(System.Data.DataRowState.Deleted)) { this.cObj.AcceptChanges(); }

#region Región de "Vínculos CCH" para AcceptChanges

#endregion
#region Región de "Vínculos RCP" para AcceptChanges

#endregion
#region Región de "Vínculos RSP" para AcceptChanges

#endregion
#region Región de "Vínculos VJE" para AcceptChanges

#endregion
#region Región de "Vínculos VRI" para AcceptChanges

#endregion
#region Región de "Vínculos JSP" para AcceptChanges

#endregion
#region Región de "Vínculos JUP" para AcceptChanges

#endregion

if (this.cObj.State.Equals(System.Data.DataRowState.Deleted)) { this.cObj.AcceptChanges(); }
}

///
/// Agrega la nueva instancia Bascula a la colección de objetos válidos para el sistema.
///

public void Add()
{
if (this.IsDetached)
{
this.ValidateAdd();

#region Código para sus acciones previas a Add.

#endregion

// Pegue en las regiones sigueintes los fragmentos de código de los vínculos correspondientes.
#region Región de "Vínculos RCP" para Add

#endregion
#region Región de "Vínculos RSP" para Add

#endregion
#region Región de "Vínculos VJE" para Add

#endregion
#region Región de "Vínculos VRI" para Add

#endregion

this.cObj.Add();

#region Código para sus acciones posteriores a Add.

#endregion

#region Región de "Vínculos CCH" para Add

#endregion
#region Región de "Vínculos JSP" para Add

#endregion
#region Región de "Vínculos JUP" para Add

#endregion

}
else
{ this.Update(); }
}

///
/// Actualiza el estado del objeto Bascula.
///

public void Update()
{
if (this.IsDetached)
{ this.Add(); }
else
{
this.ValidateUpdate();

#region Código para sus acciones previas a Update.

#endregion

// Pegue en las regiones sigueintes los fragmentos de código de los vínculos correspondientes.
#region Región de "Vínculos RCP" para Update

#endregion
#region Región de "Vínculos RSP" para Update

#endregion
#region Región de "Vínculos VJE" para Update

#endregion
#region Región de "Vínculos VRI" para Update

#endregion

this.cObj.Update();

#region Código para sus acciones posteriores a Update.

#endregion

#region Región de "Vínculos CCH" para Update

#endregion
#region Región de "Vínculos JSP" para Update

#endregion
#region Región de "Vínculos JUP" para Update

#endregion
}
}

///
/// Elimina el objeto Bascula.
///

public void Delete()
{
if (!this.IsDetached)
{
this.ValidateDelete();

#region Código para sus acciones previas a Delete.

#endregion

// Pegue en las regiones sigueintes los fragmentos de código de los vínculos correspondientes.
#region Región de "Vínculos RCP" para Delete

#endregion
#region Región de "Vínculos RSP" para Delete

#endregion
#region Región de "Vínculos RHP" para Delete
#region Código del vínculo RHP con Pesaje.
foreach (ICI.Bascula.Ctrl.Pesaje lDato in ICI.Bascula.Ctrl.Pesaje.Select(this, System.Data.DataRowState.Added | System.Data.DataRowState.Detached | System.Data.DataRowState.Deleted | System.Data.DataRowState.Modified | System.Data.DataRowState.Unchanged)) { lDato.Delete(); }
#endregion

#endregion
#region Región de "Vínculos VJE" para Delete

#endregion
#region Región de "Vínculos VRI" para Delete

#endregion
#region Región de "Vínculos JSP" para Delete

#endregion
#region Región de "Vínculos JUP" para Delete

#endregion
#region Región de "Vínculos CCH" para Delete

#endregion

this.cObj.Delete();

#region Código para sus acciones posteriores a Delete.

#endregion

#region Región de "Vínculos RHH" para Delete

#endregion
#region Región de "Vínculos JSH" para Delete

#endregion
#region Región de "Vínculos JUH" para Delete

#endregion
}
else
{
#region Región de "Vínculos RCH" para Delete

#endregion
}
}

///
/// Deshace los cambios realizados en el estado del objeto Bascula.
///

public void RejectChanges()
{
// Pegue en las regiones sigueintes los fragmentos de código de los vínculos correspondientes.
#region Código de "Variables de Estado" para RejectChanges
this.p_CamaraFrontal = null;
this.p_CamaraSuperior = null;
this.p_CamaraTrasera = null;
#endregion

#region Código para sus acciones previas a RejectChanges.

#endregion

#region Región de "Vínculos CCH" para RejectChanges

#endregion
#region Región de "Vínculos RCP" para RejectChanges

#endregion
#region Región de "Vínculos RHH" para RejectChanges

#endregion
#region Región de "Vínculos RSP" para RejectChanges

#endregion
#region Región de "Vínculos VJE" para RejectChanges

#endregion
#region Región de "Vínculos VRI" para RejectChanges

#endregion
#region Región de "Vínculos JSH" para RejectChanges

#endregion

this.cObj.RejectChanges();

#region Código para sus acciones posteriores a RejectChanges.

#endregion

#region Región de "Vínculos JSP" para RejectChanges

#endregion
#region Región de "Vínculos RCH" para RejectChanges

#endregion
#region Región de "Vínculos JUP" para RejectChanges

#endregion
#region Región de "Vínculos JUH" para RejectChanges

#endregion
}

///
/// Valida los datos de una nueva instancia de manera que pueda ser agregado a la colección de objetos Bascula válidos para el sistema. Es llamado por el método Add.
///

private void ValidateAdd()
{
#region Región de validaciones propias de la clase Bascula para aceptar la nueva instancia.

#endregion

#region Validaciones de "Vínculos RCH" para ValidateAdd.

#endregion
#region Validaciones de "Vínculos RSP" para ValidateAdd.

#endregion

this.ValidateUpdate();
}

///
/// Valida los datos de la instancia para ser modificado su estado. Es llamado por el método Update.
///

private void ValidateUpdate()
{
#region Región de validaciones propias de la clase Bascula para aceptar la actualización del estado.
if (this.Nombre.Equals("")) throw new Exception("Falta el nombre de la báscula.");

string lFilter = string.Concat("Nombre = '", this.Nombre, "'");
foreach (MIRA.Data.SerializeObject lDats in MIRA.Data.SerializeObject.Select(ICI.Bascula.Ctrl.Bascula.cMyTypeObject, lFilter))
{
if (!lDats.Same(this.cObj)) throw new Exception(string.Concat("Ya existe otra báscula con el nombre ", this.Nombre));
}

#endregion

#region Validaciones de "Vínculos RSP" para ValidateUpdate.

#endregion
#region Validaciones de "Vínculos RHH" para ValidateUpdate.

#endregion

#region Validaciones de "Vínculos JSH" para ValidateUpdate.

#endregion
#region Validaciones de "Vínculos JUH" para ValidateUpdate.

#endregion
}

///
/// Valida si se puede eliminar el objeto Bascula. Es llamado por el método Delete.
///

private void ValidateDelete()
{
#region Región de validaciones propias de la clase Bascula para aceptar la eliminación del objeto.

#endregion

#region Validaciones de "Vínculos CCP" para ValidateDelete.

#endregion
#region Validaciones de "Vínculos CSP" para ValidateDelete.

#endregion

}
#endregion

#region Selects
///
/// Selecciona todos los objetos Bascula válidos para el sistema.
///

/// <returns>Array de objetos Bascula
public static ICI.Bascula.Ctrl.Bascula[] Select()
{
return ICI.Bascula.Ctrl.Bascula.FreeSelect("", "");
}

///
/// Selecciona todos los objetos Bascula válidos para el sistema.
///

/// <param name="pState" />Estado persistente de los objetos Bascula
/// <returns>Array de objetos Bascula
public static ICI.Bascula.Ctrl.Bascula[] Select(System.Data.DataRowState pState)
{
return ICI.Bascula.Ctrl.Bascula.FreeSelect("", "", pState);
}

///
/// Obtiene la colección de objetos Bascula que cumplan con la condición.
///

/// <param name="pWhere" />Condición
/// <param name="pOrderBy" />Orden en que regresará los resultados
/// <returns>Array de objetos Bascula
/// <remarks>FreeSelect es usado solo por expertos, la cláusula pWhere debe estar en en términos de los campos de la base de datos al igual que pOrderBy.
public static ICI.Bascula.Ctrl.Bascula[] FreeSelect(String pWhere, String pOrderBy)
{
return ICI.Bascula.Ctrl.Bascula.FreeSelect(pWhere, pOrderBy, System.Data.DataRowState.Added | System.Data.DataRowState.Detached | System.Data.DataRowState.Modified | System.Data.DataRowState.Unchanged);
}

///
/// Obtiene la colección de objetos Bascula que cumplan con la condición.
///

/// <param name="pWhere" />Condición
/// <param name="pOrderBy" />Orden en que regresará los resultados
/// <param name="pState" />Estado persistente de los objetos Bascula
/// <returns>Array de objetos Bascula
/// <remarks>FreeSelect es usado solo por expertos, la cláusula pWhere debe estar en en términos de los campos de la base de datos al igual que pOrderBy.
public static ICI.Bascula.Ctrl.Bascula[] FreeSelect(String pWhere, String pOrderBy, System.Data.DataRowState pState)
{
ICI.Bascula.Ctrl.Bascula[] lThisObjs;
MIRA.Data.SerializeObject[] lSerObjs;

ICI.Bascula.Ctrl.Bascula.Initialize();
lSerObjs = MIRA.Data.SerializeObject.Select(ICI.Bascula.Ctrl.Bascula.cMyTypeObject, pWhere, pOrderBy, pState);

lThisObjs = new ICI.Bascula.Ctrl.Bascula[lSerObjs.Length];
for (Int32 X = 0; X < lSerObjs.Length; X++)
{
lThisObjs[X] = new ICI.Bascula.Ctrl.Bascula();
lThisObjs[X].cObj = lSerObjs[X];
}

return lThisObjs;

}

///
/// Obtiene de caché la colección de objetos Bascula que cumplan con la condición.
///

/// <param name="pWhere" />Condición
/// <param name="pOrderBy" />Orden en que regresará los resultados
/// <param name="pState" />Estado persistente en caché de los objetos Bascula
/// <returns>Array de objetos Bascula
/// <remarks>FreeSelect es usado solo por expertos, la cláusula pWhere debe estar en en términos de los campos de la base de datos al igual que pOrderBy.
public static ICI.Bascula.Ctrl.Bascula[] FreeSelect(String pWhere, System.Data.DataViewRowState pState, String pOrderBy)
{
ICI.Bascula.Ctrl.Bascula[] lThisObjs;
MIRA.Data.SerializeObject[] lSerObjs;

ICI.Bascula.Ctrl.Bascula.Initialize();
lSerObjs = MIRA.Data.SerializeObject.Select(ICI.Bascula.Ctrl.Bascula.cMyTypeObject, pWhere, pState, pOrderBy);

lThisObjs = new ICI.Bascula.Ctrl.Bascula[lSerObjs.Length];
for (Int32 X = 0; X < lSerObjs.Length; X++)
{
lThisObjs[X] = new ICI.Bascula.Ctrl.Bascula();
lThisObjs[X].cObj = lSerObjs[X];
}

return lThisObjs;

}

///
/// Busca y recupera el objeto Bascula identificado por el ID, si el objeto no existe regresa Null.
///

/// <param name="pID" />Identificador del objeto Bascula a buscar
/// <returns>Objeto Bascula o Null en caso de no existir.
public static ICI.Bascula.Ctrl.Bascula Find(System.Guid pID)
{
ICI.Bascula.Ctrl.Bascula lSelObj = null;

ICI.Bascula.Ctrl.Bascula.Initialize();

MIRA.Data.SerializeObject lObj = MIRA.Data.SerializeObject.Find(ICI.Bascula.Ctrl.Bascula.cMyTypeObject, pID);

if (lObj != null)
{
lSelObj = new ICI.Bascula.Ctrl.Bascula();
lSelObj.cObj = lObj;
}

return lSelObj;
}

///
/// Busca y recupera el objeto Báscula identificado por el nombre si el objeto no existe regresa Null.
///

/// <param name="pNombre" />Nombre del objeto Báscula a buscar
/// <returns>Objeto Báscula o Null en caso de no existir.
public static ICI.Bascula.Ctrl.Bascula Find(System.String pNombre)
{
string lFilter = string.Concat("Nombre = '", pNombre, "'");
ICI.Bascula.Ctrl.Bascula[] lSelObjs;
ICI.Bascula.Ctrl.Bascula lSelObj = null;

lSelObjs = ICI.Bascula.Ctrl.Bascula.FreeSelect(lFilter, "Nombre");

if (lSelObjs.Length.Equals(1))
{
lSelObj = lSelObjs[0];
}

return lSelObj;
}

///
/// Determina si el identificador se encuentra en la colección de objetos Bascula válidos o no.
///

/// <param name="pID" />Identificador del objeto Bascula
/// <returns>Verdadero en caso de sí existir el objeto Bascula, Falso en caso contrario.
public static Boolean Exist(System.Guid pID)
{
ICI.Bascula.Ctrl.Bascula.Initialize();

return MIRA.Data.SerializeObject.Exist(ICI.Bascula.Ctrl.Bascula.cMyTypeObject, pID);
}

///
/// Determina si el identificador se encuentra en la colección de objetos Bascula válidos o no.
///

/// <param name="pNombre" />Clave del objeto Bascula
/// <returns>Verdadero en caso de sí existir el objeto Bascula, Falso en caso contrario.
public static Boolean Exist(System.String pNombre)
{
string lFilter = string.Concat("Nombre = '", pNombre, "'");
ICI.Bascula.Ctrl.Bascula.Initialize();

return !MIRA.Data.SerializeObject.Select(ICI.Bascula.Ctrl.Bascula.cMyTypeObject, lFilter).Length.Equals(0);
}
#endregion

#region Copiers
///
/// Toma los datos de esta instancia Bascula y los copia en la interfaz proporcionada.
///

/// <param name="pData" />Interfaz destino
public void Get(ICI.Bascula.Ctrl.iBascula pData)
{
pData.Nombre = this.Nombre;
//pData.Status = this.Status;
pData.Unidad = this.Unidad;
pData.IP = this.IP;
pData.Comunicacion = this.Comunicacion;
pData.Hardware = this.Hardware;
pData.Calibracion = this.Calibracion;
pData.Instrumento = this.Instrumento;
pData.Continuo = this.Continuo;
pData.Puerto = this.Puerto;
pData.Baudios = this.Baudios;
pData.Paridad = this.Paridad;
pData.BitsDatos = this.BitsDatos;
pData.BitsParada = this.BitsParada;
pData.ControlFlujo = this.ControlFlujo;
pData.Peticion = this.Peticion;
pData.Respuesta = this.Respuesta;
pData.Formato = this.Formato;
pData.Overflow = this.Overflow;
pData.Underflow = this.Underflow;
//pData.LinkedPesaje = this.LinkedPesaje(object pFilter); // En caso de tener un firlto por default descomentarice esta línea y use el filtro.

pData.CamaraFrontal = this.CamaraFrontal;
pData.CamaraSuperior = this.CamaraSuperior;
pData.CamaraTrasera = this.CamaraTrasera;
}

///
/// Toma los datos de la interfaz proporcionada y los copia en esta instancia Bascula.
///

/// <param name="pData" />Interfaz origen de los datos
public void Set(ICI.Bascula.Ctrl.iBascula pData)
{
this.Nombre = pData.Nombre;
//this.Status = pData.Status;
this.Unidad = pData.Unidad;
this.IP = pData.IP;
this.Comunicacion = pData.Comunicacion;
this.Hardware = pData.Hardware;
this.Calibracion = pData.Calibracion;
this.Instrumento = pData.Instrumento;
this.Continuo = pData.Continuo;
this.Puerto = pData.Puerto;
this.Baudios = pData.Baudios;
this.Paridad = pData.Paridad;
this.BitsDatos = pData.BitsDatos;
this.BitsParada = pData.BitsParada;
this.ControlFlujo = pData.ControlFlujo;
this.Peticion = pData.Peticion;
this.Respuesta = pData.Respuesta;
this.Formato = pData.Formato;
this.Overflow = pData.Overflow;
this.Underflow = pData.Underflow;

this.CamaraFrontal = pData.CamaraFrontal;
this.CamaraSuperior = pData.CamaraSuperior;
this.CamaraTrasera = pData.CamaraTrasera;
}

///
/// Devuelve un valor String representativo de Bascula que permita reconocerlo.
///

/// <returns>Cadena con la información representativa de esta instancia.
public override String ToString()
{
return String.Concat(this.Nombre);
}

///
/// Establece la interfaz que debe ser notificada de los eventos ocurridos en Bascula.
///

/// <param name="pData" />Interfaz a notificarle los eventos.
public void Notify(ICI.Bascula.Ctrl.iBasculaNotify pData)
{
if (this.cNotify == null) { this.cNotify = new System.Collections.Generic.List<ici.bascula.ctrl.ibasculanotify>(); }
if (!this.cNotify.Contains(pData)) { this.cNotify.Add(pData); }
}

///
/// Desactiva la interfaz que era notificada por los eventos ocurridos en Bascula.
///

/// <param name="pData" />Interfaz a desactivar los eventos.
public void Quiet(ICI.Bascula.Ctrl.iBasculaNotify pData)
{
if (this.cNotify == null) { this.cNotify = new System.Collections.Generic.List<ici.bascula.ctrl.ibasculanotify>(); }
if (this.cNotify.Contains(pData)) { this.cNotify.Remove(pData); }
}
#endregion

#region Comparers
///
/// Compara dos instancias de Bascula.
///

/// <param name="pBascula" />Objeto Bascula a comparar con esta instancia
/// <returns>Verdadero si las instancias son del mismo valor, Falso en caso contrario.
public bool Equals(ICI.Bascula.Ctrl.Bascula pBascula)
{
return this.cObj.Equals(pBascula.cObj);
}

///
/// Determina si esta instancia y la pasada como argumento representan al mismo objeto.
///

/// <param name="pBascula" />Objeto a verificar
/// <returns>Verdadero si las instancias son del mismo objeto, falso en caso contrario.
public bool Same(ICI.Bascula.Ctrl.Bascula pBascula)
{
return this.cObj.Same(pBascula.cObj);
}

///
/// Compara dos instancias de la clase Bascula.
///

/// <param name="pBascula" />Objeto Bascula a comparar con esta instancia
/// <returns>1 si esta instancia es mayor a pBascula, 0 si son iguales y -1 si esta instancia es menor que pBascula
public int CompareTo(ICI.Bascula.Ctrl.Bascula pBascula)
{
// No todas las clases requeiren de implementar el método CompareTo
// Solo en el caso de que Bascula lo requiera comentarize la línea
// e implemente el código de comparación.
return this.ToString().CompareTo(pBascula.ToString());
}
#endregion

#region Links
#region Relacion Histórico Padre (RHP) con ICI.Bascula.Ctrl.Pesaje
///
/// Garantiza que los cambios se guarden en el repositorio de persistencia.
///

/// <param name="pPesaje" />Objeto Pesaje que notifica el cambio.
public bool AcceptChanges(ICI.Bascula.Ctrl.Pesaje pPesaje)
{
if (pPesaje.Bascula == null) { throw new Exception("El objeto Pesaje no se encuentra vinculado a ningún objeto Bascula. Debe usar el método Pesaje.NewObject(Bascula)."); }
if (!pPesaje.Bascula.ID.Equals(this.ID)) { throw new Exception("El objeto Pesaje ya pertenece a otro objeto Bascula."); }

if (this.IsChanged) this.AcceptChanges();

return true;
}

///
/// Actualiza el estado del objeto Bascula.
///

/// <param name="pPesaje" />Objeto Pesaje que notifica el cambio.
public bool Update(ICI.Bascula.Ctrl.Pesaje pPesaje)
{
if (pPesaje.Bascula == null) { throw new Exception("El objeto Pesaje no se encuentra vinculado a ningún objeto Bascula. Debe usar el método Pesaje.NewObject(Bascula)."); }
if (!pPesaje.Bascula.ID.Equals(this.ID)) { throw new Exception("El objeto Pesaje ya pertenece a otro objeto Bascula."); }

#region Validaciones de la vinculación "RHP" con Pesaje

#endregion

if (this.IsChanged) this.Update();

return true;
}

///
/// Deshace los cambios realizados en el estado del objeto Bascula.
///

/// <param name="pPesaje" />Objeto Pesaje que notifica el cambio.
public bool RejectChanges(ICI.Bascula.Ctrl.Pesaje pPesaje)
{
if (pPesaje.Bascula == null) { throw new Exception("El objeto Pesaje no se encuentra vinculado a ningún objeto Bascula. Debe usar el método Pesaje.NewObject(Bascula)."); }
if (!pPesaje.Bascula.ID.Equals(this.ID)) { throw new Exception("El objeto Pesaje pertenece a otro objeto Bascula."); }

#region Validaciones de la vinculación "RHP" con Pesaje

#endregion

if (this.IsChanged) this.RejectChanges();

return true;
}

///
/// Vincula el objeto Bascula con el objeto Pesaje.
///

/// <param name="pPesaje" />Objeto Pesaje a vincular con Bascula
public void Link(ICI.Bascula.Ctrl.Pesaje pPesaje)
{
if (pPesaje.Bascula == null) { throw new Exception("Proceso no autorizado. Para crear el vínculo entre Bascula y Pesaje debe usar el método Pesaje.NewObject(Bascula)."); }
if (!pPesaje.Bascula.ID.Equals(this.ID)) { throw new Exception("El objeto Pesaje ya pertenece a otro objeto Bascula."); }

#region Validaciones de la vinculación "RHP" con Pesaje

#endregion

}

///
/// Vincula el objeto Bascula con el objeto Pesaje.
///

/// <param name="pPesaje" />Objetos Pesaje a vincular con Bascula
public void Link(ICI.Bascula.Ctrl.Pesaje[] pPesaje)
{
foreach (ICI.Bascula.Ctrl.Pesaje lLnkObj in pPesaje) { this.Link(lLnkObj); }
}

///
/// Obtiene los objetos Pesaje vinculados a Bascula
///

/// <returns>Objetos Pesaje a vinculados a Bascula
public ICI.Bascula.Ctrl.Pesaje[] LinkedPesaje()
{
return ICI.Bascula.Ctrl.Pesaje.Select(this);
}

///
/// Obtiene los objetos Pesaje vinculados a Bascula
///

/// <param name="pFilter" />Filtro a aplicar en la selección de objetos Pesaje
/// <returns>Objetos Pesaje a vinculados a Bascula
// public ICI.Bascula.Ctrl.Pesaje[] LinkedPesaje(object pFilter)
// {
// return ICI.Bascula.Ctrl.Pesaje.Select(this, pFilter);
// }

///
/// Obtiene si el objeto Pesaje ya se encuentra vinculado con Bascula
///

/// <param name="pPesaje" />Objeto Pesaje a verificar
/// <returns>Verdadero si los objetos están vinculados, caso contrario Falso.
public bool Contains(ICI.Bascula.Ctrl.Pesaje pPesaje)
{
if (pPesaje.Bascula == null)
{ return false; }
else if (pPesaje.PersistentState.Equals(System.Data.DataRowState.Deleted))
{ return false; }
else
{ return pPesaje.Bascula.Same(this); }
}

///
/// Elimina el vínculo entre Bascula y Pesaje.
///

/// <param name="pPesaje" />Objeto Pesaje a eliminar el vínculo con Bascula
public void Remove(ICI.Bascula.Ctrl.Pesaje pPesaje)
{
if (this.Contains(pPesaje))
{
#region Validación de la desvinculación de Pesaje.

#endregion

switch (pPesaje.PersistentState)
{
case System.Data.DataRowState.Added:
case System.Data.DataRowState.Detached:
pPesaje.RejectChanges();
break;

case System.Data.DataRowState.Modified:
case System.Data.DataRowState.Unchanged:
pPesaje.Delete();
break;
}

}
}

///
/// Elimina el vínculo entre Bascula y Pesaje.
///

/// <param name="pPesaje" />Objetos Pesaje a eliminar el vínculo con Bascula
public void Remove(ICI.Bascula.Ctrl.Pesaje[] pPesaje)
{
foreach (ICI.Bascula.Ctrl.Pesaje lLnkObj in pPesaje)
{
this.Remove(lLnkObj);
}
}

///
/// Remplaza la colección de objetos Pesaje actualemnte vinculados con la nueva colección.
///

/// <param name="pPesaje" />Nueva colección de objetos Pesaje a vincular con Bascula
public void Replace(ICI.Bascula.Ctrl.Pesaje[] pPesaje)
{
bool lEliminar;
ICI.Bascula.Ctrl.Pesaje[] lDatosActuales = this.LinkedPesaje();

foreach (ICI.Bascula.Ctrl.Pesaje lNvoDato in pPesaje)
{ if (!this.Contains(lNvoDato)) { this.Link(lNvoDato); } }

foreach (ICI.Bascula.Ctrl.Pesaje lDatoActual in lDatosActuales)
{
lEliminar = true;
foreach (ICI.Bascula.Ctrl.Pesaje lNvoDato in pPesaje)
{
if (lDatoActual.Same(lNvoDato))
{
lEliminar = false;
break;
}
}
if (lEliminar) { this.Remove(lDatoActual); }
}
}
#endregion
#region Calificación Simple Hijo (CSH). Es calificado por MIRA.Video.Media
///
/// Obtiene o establece la cámara frontal.
///

public MIRA.Video.Media CamaraFrontal
{
get
{
if (this.p_CamaraFrontal == null)
{
if (!this.cObj.IsNull["IdCamFront"]) { this.p_CamaraFrontal = MIRA.Video.Media.Find((System.Guid)this.cObj["IdCamFront"]); }
}
return this.p_CamaraFrontal;
}
set
{
if (value == null)
{ this.cObj["IdCamFront"] = System.DBNull.Value; }
else if (value.IsDetached || value.PersistentState.Equals(System.Data.DataRowState.Added))
{ throw new Exception("El objeto Media aún no ha sido capturado y no puede ser vinculado a Bascula."); }
else
{ this.cObj["IdCamFront"] = value.ID; }

this.p_CamaraFrontal = value;
}
}

///
/// Obtiene o establece la cámara frontal.
///

public MIRA.Video.Media CamaraSuperior
{
get
{
if (this.p_CamaraSuperior == null)
{
if (!this.cObj.IsNull["IdCamSup"]) { this.p_CamaraSuperior = MIRA.Video.Media.Find((System.Guid)this.cObj["IdCamSup"]); }
}
return this.p_CamaraSuperior;
}
set
{
if (value == null)
{ this.cObj["IdCamSup"] = System.DBNull.Value; }
else if (value.IsDetached || value.PersistentState.Equals(System.Data.DataRowState.Added))
{ throw new Exception("El objeto Media aún no ha sido capturado y no puede ser vinculado a Bascula."); }
else
{ this.cObj["IdCamSup"] = value.ID; }

this.p_CamaraSuperior = value;
}
}

///
/// Obtiene o establece la cámara frontal.
///

public MIRA.Video.Media CamaraTrasera
{
get
{
if (this.p_CamaraTrasera == null)
{
if (!this.cObj.IsNull["IdCamTras"]) { this.p_CamaraTrasera = MIRA.Video.Media.Find((System.Guid)this.cObj["IdCamTras"]); }
}
return this.p_CamaraTrasera;
}
set
{
if (value == null)
{ this.cObj["IdCamTras"] = System.DBNull.Value; }
else if (value.IsDetached || value.PersistentState.Equals(System.Data.DataRowState.Added))
{ throw new Exception("El objeto Media aún no ha sido capturado y no puede ser vinculado a Bascula."); }
else
{ this.cObj["IdCamTras"] = value.ID; }

this.p_CamaraTrasera = value;
}
}

///
/// Obtiene los objetos Bascula vinculados con Media
///

/// <param name="pCamaraFrontal" />Objeto Media a obtener los objetos Bascula vinculados
/// <returns>Colección de objetos Bascula vinculados con Media
public static ICI.Bascula.Ctrl.Bascula[] Select(MIRA.Video.Media pCamaraFrontal)
{
String lQuery = String.Concat("IdCamFront = '", pCamaraFrontal.ID.ToString(), "'");
String lOrderBy = "Nombre";

return ICI.Bascula.Ctrl.Bascula.FreeSelect(lQuery, lOrderBy);
}
#endregion
#endregion

#region Calculates
#endregion

#region Notifications
#endregion

#region Methods
private void EncenderComm()
{
try
{
if (this.cSerial == null) this.cSerial = new System.IO.Ports.SerialPort();

this.cSerial.PortName = string.Concat("COM", this.Puerto.ToString());
this.cSerial.BaudRate = this.Baudios;
this.cSerial.Parity = this.Paridad;
this.cSerial.DataBits = this.BitsDatos;
this.cSerial.StopBits = this.BitsParada;
this.cSerial.Handshake = this.ControlFlujo;

this.cSerial.ReadTimeout = 500;
this.cSerial.WriteTimeout = 500;

this.p_Error = null;
this.cSerial.Open();

if (this.Continuo)
{
this.cComandoPeticion = "";
this.cProcContinuo = new System.Threading.Thread(this.LecturaContinua);
this.cProcContinuo.Start();
}
else
{
this.cComandoPeticion = this.GeneraCadena(this.Peticion);
this.cTimer.Start();
}
}
catch (Exception ex)
{
this.p_Error = ex;
if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.OnError(this, ex);
}
}
}
finally
{
if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.StatusChange(this, this.Status);
}
}
}
}

private void ApagarComm()
{
try
{
if (this.cSerial != null)
{
this.cSerial.Close();
}
}
catch (Exception ex)
{
this.p_Error = ex;

if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.OnError(this, ex);
}
}
}
finally
{
if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.StatusChange(this, this.Status);
}
}
}
}

private void EncenderIP()
{

}

private void ApagarIP()
{

}

private void EncenderVirtual()
{
this.cTimer.Start();

if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.StatusChange(this, this.Status);
}
}
}

private void ApagarVirtual()
{
this.cTimer.Stop();

if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.StatusChange(this, this.Status);
}
}
}

private void LecturaContinua()
{
while (this.Status.Equals(BasculaStatus.Encendido))
{
try
{
this.p_Peso = this.ObtenerPeso();

if (this.cSiguientePeso.CompareTo(System.DateTime.Now).Equals(-1))
{
if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.PesoChange(this, this.p_Peso);
}
}

this.cSiguientePeso = System.DateTime.Now.AddSeconds(1);
}
}
catch (Exception ex)
{
this.p_Error = ex;

if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.OnError(this, ex);
}
}
}
}
}

private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
if (this.Status.Equals(BasculaStatus.Encendido))
{
this.cTimer.Stop();

this.p_Peso = this.ObtenerPeso();

if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.PesoChange(this, this.p_Peso);
}
}

this.cTimer.Start();
}
else
{ this.cTimer.Stop(); }
}
catch (Exception ex)
{
this.p_Error = ex;
this.Status = BasculaStatus.Apagado;

if (this.cNotify != null)
{
foreach (ICI.Bascula.Ctrl.iBasculaNotify lNotif in this.cNotify)
{
lNotif.OnError(this, ex);
}
}
}
}

private string ObtenerPeso()
{
string lLectura = "";

switch (this.Comunicacion)
{
case Comunicacion.Ethernet:
break;

case Comunicacion.Serial:
if (!this.Continuo) this.cSerial.WriteLine(this.cComandoPeticion);
lLectura = this.InterpretarCadena(this.cSerial.ReadLine(), this.Respuesta);
//Peso: "\u0002 517.1LG \r" | Overflow: "\u0002 &&&&&&&LGO\r" | Underflow: "\u0002-======\0LGO\r"
break;

case Comunicacion.Virtual:
System.Random lRnd = new System.Random(System.DateTime.Now.Second);
lLectura = lRnd.Next(16000, 35000).ToString();
break;
}

return lLectura;
}

private string InterpretarCadena(string pDatos, string pFormato)
{
string lPeso = "", lPOL = "", lTX = "", lUNIT = "", lGN = "", lOver = "", lTag;
int lStrartIdx = 0, lEndIdx = 0, lDtIdx = 0, lLen = 0;
float lPesoNum = 0;

while (!pFormato.IndexOf("<", lStrartIdx).Equals(-1))
{
lStrartIdx = pFormato.IndexOf("<", lStrartIdx);
lEndIdx = pFormato.IndexOf(">", lStrartIdx);

if (lEndIdx.Equals(-1)) throw new Exception(string.Concat("El formato del comando ", pFormato, " no es correcto, falta el caracter de cierre '>' de la posición ", lStrartIdx.ToString()));
lTag = pFormato.Substring(lStrartIdx + 1, lEndIdx - lStrartIdx - 1);

if (lTag.ToUpper().Equals("STX"))
{
if (!pDatos.Substring(lDtIdx, 1).Equals("\u0002")) throw new Exception(string.Concat("Se esperaba una instrucción STX en el caracter ", lDtIdx.ToString()));
lDtIdx += 1;
}
else if (lTag.ToUpper().Equals("ETX"))
{
if (!pDatos.Substring(lDtIdx, 1).Equals("\u0003")) throw new Exception(string.Concat("Se esperaba una instrucción ETX en el caracter ", lDtIdx.ToString()));
lDtIdx += 1;
}
else if (lTag.ToUpper().Equals("CR"))
{
lDtIdx += 1;
}
else if (lTag.ToUpper().Equals("LF"))
{
lDtIdx += 1;
}
else if (lTag.ToUpper().Equals("NP"))
{
lDtIdx += 1;
}
else if (lTag.ToUpper().Equals("NULL"))
{
lDtIdx += 1;
}
else if (lTag.ToUpper().StartsWith("SP"))
{
lDtIdx += int.Parse(lTag.Substring(2, 2));
}
else if (lTag.ToUpper().StartsWith("CHR"))
{
char lChar = (char)int.Parse(lTag.Substring(3, 3));

if (lTag.IndexOf(":").Equals(-1))
//lResp = string.Concat(lResp, lChar);
lDtIdx += 1;
else
//lResp = string.Concat(lResp, this.Concatena(lChar.ToString(), int.Parse(lTag.Substring(7, 2))));
lDtIdx += int.Parse(lTag.Substring(7, 2));
}
else if (lTag.ToUpper().StartsWith("ASCII"))
{
string lChar = lTag.Substring(5, 1);

if (lTag.IndexOf(":").Equals(-1))
//lResp = string.Concat(lResp, lChar);
lDtIdx += 1;
else
//lResp = string.Concat(lResp, this.Concatena(lChar.ToString(), int.Parse(lTag.Substring(7, 2))));
lDtIdx += int.Parse(lTag.Substring(7, 2));
}
else if (lTag.ToUpper().StartsWith("TX="))
{
lLen = lTag.Substring(3).Length;
lTX = pDatos.Substring(lDtIdx, lLen);

if (!lTag.Substring(3).ToUpper().Equals(lTX.ToUpper())) throw new Exception(string.Concat("Se esperaba el texto ", lTag.Substring(3), " en la posición ", lDtIdx.ToString(), " pero se recibió el dato ", lTX, "."));
lDtIdx += lLen;
}
else if (lTag.ToUpper().StartsWith("TX"))
{
lLen = int.Parse(lTag.Substring(2, 2));
lTX = pDatos.Substring(lDtIdx, lLen);
lDtIdx += lLen;
}
else if (lTag.ToUpper().StartsWith("W"))
{
lLen = int.Parse(lTag.Substring(1, 2));
lPeso = pDatos.Substring(lDtIdx, lLen);
lDtIdx += lLen;
}
else if (lTag.ToUpper().StartsWith("POL"))
{
lPOL = pDatos.Substring(lDtIdx, 1);
lDtIdx += 1;
}
else if (lTag.ToUpper().StartsWith("UNIT"))
{
lLen = int.Parse(lTag.Substring(4, 2));
lUNIT = pDatos.Substring(lDtIdx, lLen);
lDtIdx += lLen;
}
else if (lTag.ToUpper().StartsWith("GN"))
{
lGN = pDatos.Substring(lDtIdx, 1);
lDtIdx += 1;
}
else if (lTag.ToUpper().StartsWith("O"))
{
lOver = pDatos.Substring(lDtIdx, 1);
lDtIdx += 1;
}
else
{
throw new Exception(string.Concat("El formato <", lTag, "> del comando ", pFormato, " no se logró interpretar, no se reconoce este dato."));
}

lStrartIdx = lEndIdx;
}

if (lOver.Equals("O"))
{
this.p_PesoNum = 8888888888;

if (lPOL.Equals("-"))
lPeso = "UNDER";
else
lPeso = "OVER";
}
else if (float.TryParse(lPeso, out lPesoNum))
{
if (lPOL.Equals("-")) lPesoNum = -lPesoNum;
lPeso = lPesoNum.ToString(this.Formato);
this.p_PesoNum = lPesoNum;
}
else
{ this.p_PesoNum = 0; }

return lPeso;
}

private string GeneraCadena(string pComando)
{
string lResp = "", lPeti;
int lStrartIdx = 0, lEndIdx = 0;

while (!pComando.IndexOf("<", lStrartIdx).Equals(-1))
{
lStrartIdx = pComando.IndexOf("<", lStrartIdx);
lEndIdx= pComando.IndexOf(">", lStrartIdx);

if (lEndIdx.Equals(-1)) throw new Exception(string.Concat("El formato del comando ", pComando, " no es correcto, falta el caracter de cierre '>' de la posición ", lStrartIdx.ToString()));
lPeti = pComando.Substring(lStrartIdx + 1, lEndIdx - lStrartIdx - 1);

if (lPeti.ToUpper().Equals("STX"))
{
lResp = string.Concat(lResp, "\u0002");
}
else if (lPeti.ToUpper().Equals("ETX"))
{
lResp = string.Concat(lResp, "\u0003");
}
else if (lPeti.ToUpper().Equals("CR"))
{
lResp = string.Concat(lResp, "\r");
}
else if (lPeti.ToUpper().Equals("LF"))
{
lResp = string.Concat(lResp, "\n");
}
else if (lPeti.ToUpper().Equals("NP"))
{
lResp = string.Concat(lResp, "\f");
}
else if (lPeti.ToUpper().Equals("NULL"))
{
lResp = string.Concat(lResp, "\0");
}
else if (lPeti.ToUpper().StartsWith("SP"))
{
lResp = string.Concat(lResp, this.Concatena(" ", int.Parse(lPeti.Substring(2, 2))));
}
else if (lPeti.ToUpper().StartsWith("CHR"))
{
char lChar = (char)int.Parse(lPeti.Substring(3, 3));

if (lPeti.IndexOf(":").Equals(-1))
lResp = string.Concat(lResp, lChar);
else
lResp = string.Concat(lResp, this.Concatena(lChar.ToString(), int.Parse(lPeti.Substring(7, 2))));
}
else if (lPeti.ToUpper().StartsWith("ASCII"))
{
string lChar = lPeti.Substring(5, 1);

if (lPeti.IndexOf(":").Equals(-1))
lResp = string.Concat(lResp, lChar);
else
lResp = string.Concat(lResp, this.Concatena(lChar.ToString(), int.Parse(lPeti.Substring(7, 2))));
}
else if (lPeti.ToUpper().StartsWith("TX="))
{
lResp = string.Concat(lResp, lPeti.Substring(3));
}
else
{
throw new Exception(string.Concat("El formato <", lPeti, "> del comando ", pComando, " no se logró interpretar, no se reconoce este dato."));
}

lStrartIdx = lEndIdx;
}

return lResp;
}

private string Concatena(string pCadena, int pVeces)
{
string lResp = "";

for (int X = 0; X < pVeces; X++)
{
lResp = string.Concat(lResp, pCadena);
}

return lResp;
}
#endregion
}



///
/// Enumera los estados de la báscula.
///

public enum BasculaStatus
{
///
/// La báscula se encuentra o se establece en funcionamiento.
///

Encendido,
///
/// La bascula se encuentra o establece en apagada.
///

Apagado,
///
/// La báscula marca un error.
///

Error
}



///
/// Enumera el tipo de comunicación con el hardware.
///

public enum Comunicacion
{
///
/// La comunicación con el hardware es de tipo serial.
///

Serial,
///
/// La comunicación con el hardware es por Ethernet.
///

Ethernet,
///
/// La báscula es virtual (usualmente para pruebas).
///

Virtual
}



///
/// Enumera el tipo de hardware con el que la clase Bascula de este ensamblado puede comunicarse.
///

public enum Hardware
{
Ricelake_920i,
Ricelake_480,
Ricelake_720,
Ricelake_820
}



///
/// Interfaz que deberán implementar las clases que deban ser notificadas de eventos en Bascula.
///

public interface iBasculaNotify
{
void OnError(ICI.Bascula.Ctrl.Bascula sender, System.Exception Error);
void StatusChange(ICI.Bascula.Ctrl.Bascula sender, ICI.Bascula.Ctrl.BasculaStatus Status);
void PesoChange(ICI.Bascula.Ctrl.Bascula sender, string Peso);
}



///
/// Interfaz que deberán implementar las clases que intercambien datos con Bascula.
///

public interface iBascula
{
string Nombre { get; set; }
string Unidad { get; set; }
string IP { get; set; }
ICI.Bascula.Ctrl.Comunicacion Comunicacion { get; set; }
ICI.Bascula.Ctrl.Hardware Hardware { get; set; }
string Calibracion { get; set; }
string Instrumento { get; set; }
bool Continuo { get; set; }
int Puerto { get; set; }
int Baudios { get; set; }
System.IO.Ports.Parity Paridad { get; set; }
int BitsDatos { get; set; }
System.IO.Ports.StopBits BitsParada { get; set; }
System.IO.Ports.Handshake ControlFlujo { get; set; }
string Peticion { get; set; }
string Respuesta { get; set; }
string Formato { get; set; }
string Overflow { get; set; }
string Underflow { get; set; }
ICI.Bascula.Ctrl.Pesaje[] LinkedPesaje { set; }

MIRA.Video.Media CamaraFrontal { get; set; }
MIRA.Video.Media CamaraSuperior { get; set; }
MIRA.Video.Media CamaraTrasera { get; set; }
}

}
GeneralRe: POOV: is most similar to the technique used an orm of type active record Pin
AMC30-Jan-19 16:59
AMC30-Jan-19 16:59 
AnswerMessage Closed Pin
1-May-17 22:07
Eduardo Mireles1-May-17 22:07 
QuestionRepetitive code, multiple responsibilities and transactions Pin
Paulo Zemek29-Oct-16 7:55
mvaPaulo Zemek29-Oct-16 7:55 
AnswerRe: Repetitive code, multiple responsibilities and transactions Pin
Eduardo Mireles30-Oct-16 11:48
Eduardo Mireles30-Oct-16 11:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.